如何将变量从主机上的自定义类数组复制到CUDA中的设备上的float数组中

时间:2013-12-27 15:32:11

标签: c++ arrays cuda

我正在使用CUDA。我在主持人上有以下课程:

class Particle{
     public:
     float x;
     float v;
     // several other variables
}

然后我有一个粒子矢量

vector <Particle> p_all(512);

在GPU上,我想操作所有x的数组(取自所有粒子),并希望将数据从Particles数组复制到设备上的浮点数组中。我有预感可以使用cudaMemcpy,我尝试了下面的代码,但它给出了无效的音高错误。

cudaMalloc( (void**) &pos_dev, sizeof(float)*512);
cudaMemcpy2D( (void*) &pos_dev, sizeof(float), (void*)&p_all[0].x, sizeof(Particle), sizeof(Particle), 512*sizeof(float), cudaMemcpyHostToDevice);

是否可以这样做?当然,备份解决方案是使用for循环创建一个x数组,然后将其复制到设备。但我正在寻找一种更有效的解决方案。

感谢。

以下完整代码。

#include <cuda_runtime.h>
#include <iostream>
#include <vector>
using namespace std;

// This will output the proper error string when calling cudaGetLastError
void getLastCudaError(string s=""){
    string errMessage = s;
    cudaError_t err = cudaGetLastError();
    if( err != cudaSuccess){
        cerr << __FILE__ << "(" << __LINE__ << ") : Last Cuda Error - " << errMessage 
             << " (" << int(err) << "): " << cudaGetErrorString(err) << ".\n";
        exit(-1);
    }
}

class Particle{
    public:
    float x;
    float v;
    int a;
    char c;
    short b;

    Particle(){
        a=1988; c='a'; v=5.56; x=1810; b=1.66;
    }
};

template <class T>
void printVec(vector <T> &v, string name = "v"){
    cout << name << " = ";
    for (int i=0; i<v.size(); ++i) cout << v[i] << " " ;
    cout << '\n';
}

int main(){

    const int N = 512;
    vector <float> pos(N,5);

    vector <Particle> p_all(N);

    float * pos_dev;
    float * vel_dev;

    cudaMalloc( (void**) &pos_dev, sizeof(float)*N);

    printVec(pos, "pos");

    cudaMemcpy2D( (void*) &pos_dev, sizeof(float), (void*)&(p_all[0].x), sizeof(Particle), sizeof(float), N, cudaMemcpyHostToDevice);
    getLastCudaError("HtoD");

    cudaMemcpy( (void*) &pos[0], (void*)&pos_dev, N*sizeof(float), cudaMemcpyDeviceToHost);
    getLastCudaError("DtoH");

    printVec(pos, "pos_new");

    return 0;

}

2 个答案:

答案 0 :(得分:0)

您将数据分配为“结构数组”,例如

class Particle{
    public:
        float x;
        float v;
}

Particle foo[N];

由于数据交错会导致合并问题,因此您尝试使用cudaMemcpy2D。在带宽利用方面更方便的解决方案是将数据分配为“阵列结构”

class Particle{
    public:
        float x[N];
        float v[N];
}

Particle foo;

通过这种方式,您可以避免使用cudaMemcpy2D并通过简单的cudaMemcpy将数据从主机复制到设备。

答案 1 :(得分:0)

您的cudaMemcpy2D来电设置不正确。查看documentation

试试这个:

cudaMemcpy2D( (void*) pos_dev, sizeof(float), (void*)&(p_all[0].x), sizeof(Particle), sizeof(float), 512, cudaMemcpyHostToDevice);

有多个参数需要修改,但是无效的音高错误是因为请求的传输宽度(以sizeof(Particle)为单位)比目标音高(sizeof(float)更宽,这是正确的)

编辑:此外,虽然您没有询问,但您现在发布的代码中的最终cudaMemcpy操作也是错误的。以下更改应该有所帮助:

cudaMemcpy( (void*) &(pos[0]), (void*)pos_dev, N*sizeof(float), cudaMemcpyDeviceToHost);