我已经观看了录制的openacc概述课程视频,直到第3讲,其中讨论了表达数据移动。如何使用gsl_matrix*
将copy_in()
从cpu移动到gpu。例如,在CPU上我可以做类似的事情,
gsl_matrix *Z = gsl_matrix_calloc(100, 100),
这将给我一个100x100的零矩阵。现在Z是指向gsl_matrix结构的指针,看起来像
typedef struct{
size_t size1;
size_t size2;
size_t tda;
double * data;
gsl_block * block;
int owner;
} gsl_matrix;
如何使用copyin()
表示从CPU到GPU的Z(这是一个指针)的数据移动?
答案 0 :(得分:1)
我无法直接谈论在OpenACC数据和计算区域内使用GSL,但可以为您提供有关动态数据成员的聚合类型的一般答案。
假设您使用PGI编译器和更新的NVIDIA设备,首先要尝试的是CUDA统一内存(UVM)。使用标志" -ta = tesla:managed"进行编译,所有动态分配的数据都将由CUDA运行时管理,因此您不需要自己管理数据移动。有涉及的开销和警告,但它使事情更容易上手。请注意,PGI 16.9或更高版本附带的CUDA 8.0可提高UVM性能。
如果没有UVM,您需要执行数据的手动深层复制。以下是您首先在设备上创建父结构并执行浅表复制的基本概念。接下来创建动态数组" data"在设备上,将初始值复制到数组,然后将数据的设备指针附加到设备结构的数据指针。因为"阻止"它本身就是一个包含动态数据成员的结构数组,您需要遍历数组,在设备上创建它的数据数组。
matrix * mat = (matrix*) malloc(sizeof(matrix));
#pragma acc enter data copyin(mat)
// Change this to the correct size of "data" and blocks
#pragma acc enter data copyin(mat.data[0:dataSize]);
#pragma acc enter data copyin(mat.block[0:blockSize]);
for (i=0; i < blockSize; ++i) {
#pragma acc enter data copyin(mat.block[i].data[0:mat.block[i].size])
}
要删除,请再次走结构,从下往上删除
for (i=0; i < blockSize; ++i) {
#pragma acc exit data delete(mat.block[i].data)
}
#pragma acc exit data delete(mat.block);
#pragma acc exit data delete(mat.data);
#pragma acc exit data delete(mat);
更新时,请务必仅更新基本数据类型的标量或数组。即更新&#34;数据&#34;但不是&#34;阻止&#34;。更新执行浅拷贝,因此更新&#34;阻止&#34;会更新导致非法地址的主机或设备指针。
最后,一定要把矩阵变量放在&#34; present&#34;在计算区域中使用它时的子句。
#pragma acc parallel loop present(mat)