尝试将结构复制到设备内存时 CUDA 参数无效 (cudaMemcpy)

CUDA invalid argument when trying to copy struct to device's memory (cudaMemcpy)

本文关键字:参数 CUDA 无效 cudaMemcpy 内存 结构 复制      更新时间:2023-10-16

我试图弄清楚我应该如何创建一个注定要发送到设备的结构/类,但我一直得到这个"无效参数"CUDA错误。我做了一个显示错误的小示例:

#include <iostream>
#include <cstdio>
using namespace std;
#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
        cudaGetErrorString(XXX) << ", at line " << __LINE__ 
        << endl; cudaDeviceSynchronize(); } while (0)
struct P {
    double x,y;
    __host__ __device__ void init(const double &a, const double &b) {
        x = a; y = b; }
};
int main(int argc, char **argv)
{
    P hP, hQ, dP;
    cout << "Size of P: " << sizeof(P) << endl;
    CUDA_WARN(cudaMalloc((void**) &dP, sizeof(P)));
    printf("dP: %pn", &dP); // print dP's address on the device
    hP.init(1.2,-2.1);
    hQ.init(0.,0.);
    CUDA_WARN(cudaMemcpy(&dP, &hP, sizeof(P), cudaMemcpyHostToDevice));
    CUDA_WARN(cudaMemcpy(&hQ, &dP, sizeof(P), cudaMemcpyDeviceToHost));
    cout << "Copy back: " << hQ.x << "t" << hQ.y << endl;
    dP.init(3.,3.);
    CUDA_WARN(cudaMemcpy(&hP, &dP, sizeof(P), cudaMemcpyDeviceToHost));
    cout << "Copy new:  " << hP.x << "t" << hP.y << endl;
    return 0;
}

我正在编译(我的卡是特斯拉C2050):

nvcc -arch sm_20 -o exec file.cu

得到的结果是:

Size of P: 16
dP: 0x7fff82d4b7b0
CUDA Error: invalid argument, at line 24
CUDA Error: invalid argument, at line 25
Copy back: 0    0
CUDA Error: invalid argument, at line 28
Copy new:  1.2  -2.1

------------------
(program exited with code: 0)
Press return to continue

如果你们能帮助我,谢谢你们!

======在@talonmies, @JackOLantern, @Robert Crovella评论后=======

谢谢,伙计们!你真的帮了大忙!根据注释,我可以纠正我的代码,现在它正在工作。只是为了注册最终解决方案:

#include <iostream>
#include <cstdio>
using namespace std;
#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
        cudaGetErrorString(XXX) << ", at line " << __LINE__ 
        << endl; cudaDeviceSynchronize(); } while (0)
struct P {
    double x,y;
    __host__ __device__ void init(const double &a, const double &b) {
        x = a; y = b; }
};
/* INCLUDED KERNEL FUNCTION */
__global__ void dev_P_init(P *p, double a, double b) {
    p->init(a,b);
}
int main(int argc, char **argv)
{
    P hP, hQ, *dP; //*changed*
    cout << "Size of P: " << sizeof(P) << endl;
    CUDA_WARN(cudaMalloc((void**) &dP, sizeof(P)));
    printf("dP: %pn", &dP); // print dP's address on the device
    hP.init(1.2,-2.1);
    hQ.init(0.,0.);
    CUDA_WARN(cudaMemcpy(dP, &hP, sizeof(P), cudaMemcpyHostToDevice)); //*changed*
    CUDA_WARN(cudaMemcpy(&hQ, dP, sizeof(P), cudaMemcpyDeviceToHost)); //*changed*
    cout << "Copy back: " << hQ.x << "t" << hQ.y << endl;
    dev_P_init<<< 1, 1 >>>(dP,3., 3.); //*call to kernel*
    CUDA_WARN(cudaMemcpy(&hP, dP, sizeof(P), cudaMemcpyDeviceToHost)); //*changed*
    cout << "Copy new:  " << hP.x << "t" << hP.y << endl;
    return 0;
}

校正输出:

Size of P: 16
dP: 0x7fff6fa2e498
Copy back: 1.2  -2.1
Copy new:  3    3

------------------
(program exited with code: 0)
Press return to continue

@talonmies已经注意到,&dP不是一个有效的设备指针。实际上,dP是驻留在主机上的一个变量,因此它的地址指向主机内存空间。与此相反,当dP是指针时,cudaMalloc将其值作为参数接收,其值指向设备内存空间。

这是你的代码的正确版本:

#include <iostream>
#include <cstdio>
using namespace std;
#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
    cudaGetErrorString(XXX) << ", at line " << __LINE__ 
    << endl; cudaDeviceSynchronize(); } while (0)
struct P {
    double x,y;
    __host__ __device__ void init(const double &a, const double &b) {
    x = a; y = b; }
};
int main(int argc, char **argv)
{
    P *dP;
    P hP, hQ;
    CUDA_WARN(cudaMalloc((void**) &dP, sizeof(P)));
    CUDA_WARN(cudaMemcpy(dP, &hP, sizeof(P), cudaMemcpyHostToDevice));
    CUDA_WARN(cudaMemcpy(&hQ, dP, sizeof(P), cudaMemcpyDeviceToHost));
    CUDA_WARN(cudaMemcpy(&hP, dP, sizeof(P), cudaMemcpyDeviceToHost));
    return 0;
}