jinglei
jinglei

Reputation: 3363

cuda - cudaInvalidValue error when cudaMemcpyToSymbol

I'm trying to copy an array of double to a chunk of constant memory on device. But get cudaInvalidValue error.

Here's my code.

#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!");
    }

From the link, it says cudaInvalidValue is due to one or more of the parameters passed to the API call is not within an acceptable range of values.

But I think I pass two pointers and the size of copied item is correct. What is the problem then?

Upvotes: 0

Views: 254

Answers (1)

talonmies
talonmies

Reputation: 72351

This:

__constant__ double *dev_CIE_X;

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

is illegal. __constant__ memory cannot be dynamically allocated and device symbols cannot be directly manipulated from the host in this manner. You could do this:

__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);

But then you need to understand that the array is stored in global memory and only the pointer value is stored in constant memory.

What you probably want is something like this:

__constant__ double dev_CIE_X[kCIELEN];

// populate CIE_X

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

i.e. statically declare the array in constant memory and then copy the host data to that array.

Upvotes: 2

Related Questions