我想从主机到设备复制动态分配的2D数组以获得其离散傅里叶变换。
我正在使用下面的代码将数组复制到设备
cudaMalloc((void**)&array_d, sizeof(cufftComplex)*NX*(NY/2+1));
cudaMemcpy(array_d, array_h, sizeof(float)*NX*NY, cudaMemcpyHostToDevice);
这适用于静态数组,我从我的fft获得预期的输出。 但它不适用于动态数组。经过一点点搜索,我了解到我无法将这样的动态数组从主机复制到设备。所以我找到了这个解决方案。
cudaMalloc((void**)&array_d, sizeof(cufftComplex)*NX*(NY/2+1));
for(int i=0; i<NX; ++i){
cudaMemcpy(array_d+ i*NY, array_h[i], sizeof(float)*NY, cudaMemcpyHostToDevice);
}
但由于我从fft中得到了错误的值,所以它也没有正确执行任务。
以下是我的fft代码。
cufftPlanMany(&plan, NRANK, n,NULL, 1, 0,NULL, 1, 0,CUFFT_R2C,BATCH);
cufftSetCompatibilityMode(plan, CUFFT_COMPATIBILITY_NATIVE);
cufftExecR2C(plan, (cufftReal*)data, data);
cudaThreadSynchronize();
cudaMemcpy(c, data, sizeof(float)*NX*NY, cudaMemcpyDeviceToHost);
我该如何克服这个问题?
修改
以下是代码
#define NX 4
#define NY 5
#define NRANK 2
#define BATCH 10
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <cufft.h>
#include <stdio.h>
#include <iostream>
int check();
int main()
{
// static array
float b[NX][NY] ={
{0.7943 , 0.6020 , 0.7482 , 0.9133 , 0.9961},
{0.3112 , 0.2630 , 0.4505 , 0.1524 , 0.0782},
{0.5285 , 0.6541 , 0.0838 , 0.8258 , 0.4427},
{0.1656 , 0.6892 , 0.2290 , 0.5383 , 0.1067}
};
// dynamic array
float **a = new float*[NX];
for (int r = 0; r < NX; ++r)
{
a[r] = new float[NY];
for (int c = 0; c < NY; ++c)
{
a[r][c] = b[r][c];
}
}
// arrray to store the results - host side
float c[NX][NY] = { 0 };
cufftHandle plan;
cufftComplex *data;
int n[NRANK] = {NX, NY};
cudaMalloc((void**)&data, sizeof(cufftComplex)*NX*(NY/2+1));
cudaMemcpy(data, b, sizeof(float)*NX*NY, cudaMemcpyHostToDevice);
/* Create a 2D FFT plan. */
cufftPlanMany(&plan, NRANK, n,NULL, 1, 0,NULL, 1, 0,CUFFT_R2C,BATCH);
cufftSetCompatibilityMode(plan, CUFFT_COMPATIBILITY_NATIVE);
cufftExecR2C(plan, (cufftReal*)data, data);
cudaThreadSynchronize();
cudaMemcpy(c, data, sizeof(float)*NX*NY, cudaMemcpyDeviceToHost);
cufftDestroy(plan);
cudaFree(data);
return 0;
}
答案 0 :(得分:0)
data
属于cufftComplex
类型,是一系列typedef,最终产生float2
。这意味着data + n
将data
n
个float2
类型的对象推进2 * n
,或float
data
类型的对象推进cufftExecR2C()
。这使得“动态阵列”复制不正确;你必须将for(int i=0; i<NX; ++i){
cudaMemcpy(reinterpret_cast<float*>(data) + i*NY, a[i], sizeof(float)*NY, cudaMemcpyHostToDevice);
}
的增量减半。
修改强>
查看new float[NX * NY]
的参数类型,我认为这应该有效:
std::vector
旁注:您实际上没有动态2D数组(即a
)。你拥有的是动态浮点数组的动态指针数组。我相信使用真正的2D数组会更有意义,这样你就可以保留静态案例的复制代码。
由于您已经标记了此C ++,因此您应该认真考虑使用std::vector<float> a(NX * NY);
而不是手动管理动态内存。也就是说,像这样更改NX
:
NY
当你接触它时,我建议将const size_t NX = 4;
const size_t NY = 5;
,{{1}}等从宏转换为常量:
{{1}}
等