cuda - cudaMemcpyToSymbol 时出现 cudaInvalidValue 错误

cuda - cudaInvalidValue error when cudaMemcpyToSymbol

我正在尝试将双精度数组复制到设备上的一块常量内存中。但是得到 cudaInvalidValue 错误。

这是我的代码。

#define kCIELEN 95  // length of CIE_X[]

const double CIE_X[] = {
        1.299000e-04, 2.321000e-04, 4.149000e-04, 7.416000e-04, 1.368000e-03,
        2.236000e-03, 4.243000e-03, 7.650000e-03, 1.431000e-02, 2.319000e-02,
        4.351000e-02, 7.763000e-02, 1.343800e-01, 2.147700e-01, 2.839000e-01,
        3.285000e-01, 3.482800e-01, 3.480600e-01, 3.362000e-01, 3.187000e-01,
        2.908000e-01, 2.511000e-01, 1.953600e-01, 1.421000e-01, 9.564000e-02,
        5.795001e-02, 3.201000e-02, 1.470000e-02, 4.900000e-03, 2.400000e-03,
        9.300000e-03, 2.910000e-02, 6.327000e-02, 1.096000e-01, 1.655000e-01,
        2.257499e-01, 2.904000e-01, 3.597000e-01, 4.334499e-01, 5.120501e-01,
        5.945000e-01, 6.784000e-01, 7.621000e-01, 8.425000e-01, 9.163000e-01,
        9.786000e-01, 1.026300e+00, 1.056700e+00, 1.062200e+00, 1.045600e+00,
        1.002600e+00, 9.384000e-01, 8.544499e-01, 7.514000e-01, 6.424000e-01,
        5.419000e-01, 4.479000e-01, 3.608000e-01, 2.835000e-01, 2.187000e-01,
        1.649000e-01, 1.212000e-01, 8.740000e-02, 6.360000e-02, 4.677000e-02,
        3.290000e-02, 2.270000e-02, 1.584000e-02, 1.135916e-02, 8.110916e-03,
        5.790346e-03, 4.106457e-03, 2.899327e-03, 2.049190e-03, 1.439971e-03,
        9.999493e-04, 6.900786e-04, 4.760213e-04, 3.323011e-04, 2.348261e-04,
        1.661505e-04, 1.174130e-04, 8.307527e-05, 5.870652e-05, 4.150994e-05,
        2.935326e-05, 2.067383e-05, 1.455977e-05, 1.025398e-05, 7.221456e-06,
        5.085868e-06, 3.581652e-06, 2.522525e-06, 1.776509e-06, 1.251141e-06
};

__constant__ double *dev_CIE_X;

cudaStatus = cudaMalloc((void**)&dev_CIE_X, kCIELEN * sizeof(double));
if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMalloc failed!");
}

// below do not work, so try to use a pointer `*ciex`
// cudaStatus = cudaMemcpyToSymbol(dev_CIE_X, &CIE_X, kCIELEN * sizeof(double));

double *ciex = new double[kCIELEN];
for (int i = 0; i < kCIELEN; i++) {
    ciex[i] = CIE_X[i];
}


cudaStatus = cudaMemcpyToSymbol(dev_CIE_X, &ciex, kCIELEN * sizeof(double));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
    }

link,它说cudaInvalidValue是由于传递给API调用的一个或多个参数不在可接受的范围内值.

但我想我传递了两个指针,复制项目的大小是正确的。那有什么问题呢?

这个:

__constant__ double *dev_CIE_X;

cudaStatus = cudaMalloc((void**)&dev_CIE_X, kCIELEN * sizeof(double));
if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMalloc failed!");
}

是非法的。 __constant__ 无法动态分配内存,并且无法以这种方式从主机直接操作设备符号。你可以这样做:

__constant__ double *dev_CIE_X;
double *h_dev_CIE_X;
cudaMalloc((void**)&h_dev_CIE_X, kCIELEN * sizeof(double));

cudaMemcpyToSymbol(dev_CIE_X, &h_dev_CIE_X, sizeof(double));

// populate CIE_X

cudaMemcpy(h_dev_CIE_X, &CIE_X[0], kCIELEN * sizeof(double), cudaMemcpyHostToDevice);

但是你需要明白,数组存储在全局内存中,只有指针值存储在常量内存中。

你可能想要的是这样的:

__constant__ double dev_CIE_X[kCIELEN];

// populate CIE_X

cudaMemcpyToSymbol(dev_CIE_X, &CIE_X[0], kCIELEN * sizeof(double));

即在常量内存中静态声明数组,然后将主机数据复制到该数组。