我正在编写mex C / Cuda / Cublas代码,并在Matlab的2018a之前版本中以复杂格式存储拆分数据。但是,cuBlas例程使用交错格式。因此,在调用cuBlas之前,需要将格式从split更改为interleaved,并在返回到matlab之前将其交错更改为split。
简而言之,假设double
数组Ar
和Ai
分别是cuDoubleComplex
数组A
的实部和虚部。我想知道执行以下副本的最有效方法:
Ar
和Ai
复制到设备内存中的A
。 A
复制到主机内存中的Ar
和Ai
中。最初我做了类似以下的事情:
cudaDeviceSynchronize();
tic=getHighResolutionTime();
//Copy Ar and Ai into a A element by element, interleaving them in host memory.
double2cuDoubleComplex(A,Ar,Ai,SIZE);
//Copy A to the device. A->d_A
cuDoubleComplex *dA;
cudaMalloc((void**)&d_A,sizeof(cuDoubleComplex)*SIZE);
cudaMemcpy(d_A,A, sizeof(cuDoubleComplex)*SIZE,cudaMemcpyHostToDevice);
/*** call cublas here overwriting d_A here ***/
//Copy the result from device back to host. d_A->A
cudaMemcpy(A,d_A,sizeof(cuDoubleComplex)*SIZE,cudaMemcpyDeviceToHost);
//Copy A into Ar and Ai element by element, splitting it in host memory.
cuDoubleComplex2double(A,Ar,Ai,SIZE);
cudaDeviceSynchronize();
toc=getHighResolutionTime();
printf("\n%f",toc-tic);
上面的方法很浪费,因为交错/分割数组需要逐个元素地复制,并且需要分配一个额外的临时主机变量。因此,我改为尝试使用suggestion to use pitched cudaMemcpy2D来在传输过程中拆分和交错阵列。我的实现类似于以下内容:
cudaDeviceSynchronize();
tic=getHighResolutionTime();
//interleave the real and imag parts while copying the data to the device
double *d_A;
cudaMalloc((void**)&d_A,sizeof(double)*2*SIZE);
cudaMemcpy2D(d_A,2*sizeof(double),Ar,sizeof(double),sizeof(double),SIZE,cudaMemcpyHostToDevice);
cudaMemcpy2D(d_A+1,2*sizeof(double),Ai,sizeof(double),sizeof(double),SIZE,cudaMemcpyHostToDevice);
cuDoubleComplex *d_A=(cuDoubleComplex*)d_A;
/*** call cublas here overwriting d_A here ***/
//split the interleaved complex data while copying it back from the device
d_A=(double*)d_A;
cudaMemcpy2D(Ar,sizeof(double),d_A,2*sizeof(double),sizeof(double),SIZE,cudaMemcpyDeviceToHost);
cudaMemcpy2D(Ai,sizeof(double),d_A+1,2*sizeof(double),sizeof(double),SIZE,cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
toc=getHighResolutionTime();
printf("\n%f",toc-tic);
但是,第二种方法的效率甚至比第一种方法低(慢两倍)!我通过评论cublas调用(如上所示)并检查以上代码片段的时间来进行检查。我使用了一个大的SIZE=16800^2
来确保准确性,并对它们进行了多次计时。
在两种情况下,主机和设备之间传输的数据量是相同的。当第一种方法涉及分配临时变量以及逐元素复制时,为什么第二种方法较慢?
我做错什么了吗?有没有更好的方法来制作我在帖子开头提到的副本?