在CUDA中将动态分配的2D阵列从主机复制到设备

时间:2013-12-27 09:04:15

标签: c++ arrays cuda fft dynamic-arrays

我想从主机到设备复制动态分配的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;
    }

1 个答案:

答案 0 :(得分:0)

data属于cufftComplex类型,是一系列typedef,最终产生float2。这意味着data + ndata nfloat2类型的对象推进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}}