CUDA从主机到设备复制填充数据的数组数组

时间:2017-10-04 00:20:25

标签: c arrays cuda

我一直在寻找一种方法,将填充的阵列数组主机传输到CUDA中的 device

我有什么:

  • 数据填充的全局数组,我需要将其复制到设备以执行内核。
  • 数组中的数组长度不同。

我有一个函数来启动数组及其值:

double** weights; // globally defined in host
int init_weigths(){
    weights = (double**) malloc(sizeof(double*) * SIZE);

    for (int i = 0; i < SIZE; i++) {
        weights[i] = (double*) malloc(sizeof(double) * getSize(i));

        for (int j = 0; j < getSize(i); j++){
            weights[i][j] = get_value(i,j);
        }
    }
}

我的(不工作)解决方案

我设计了一个收集互联网上其他答案信息的解决方案,但没有人工作。我认为这是因为我的数组数组已经填满了信息,以及所包含数组的可变长度。

我所拥有的解决方案,即在所有cudaMemcpy次来电,以及第二次和更进一步的cudaMalloc来电中抛出“无效参数”错误;由cudaGetLastError()检查。 解决方案就是这个:

double** d_weights;
int init_cuda_weight(){
    cudaMalloc((void **) &d_weights, sizeof(double*) * SIZE);

    double** temp_d_ptrs = (double**) malloc(sizeof(double*) * SIZE);
    // temp array of device pointers
    for (int i = 0; i < SIZE; i++){
        cudaMalloc((void**) &temp_d_ptrs[getSize(i)],
                sizeof(double) * getSize(i));
        // ERROR CHECK WITH cudaGetLastError(); doesn't throw any errors ar first.
        cudaMemcpy(temp_d_ptrs[getSize(i)], weights[getSize(i)], sizeof(double) * getSize(i), cudaMemcpyHostToDevice);
        // ERROR CHECK WITH cudaGetLastError(); throw "invalid argument" error for now and beyond.
    }

   cudaMemcpy(d_weights, temp_d_ptrs, sizeof(double*) * SIZE,
        cudaMemcpyHostToDevice);
}

作为附加信息,我已经简化了一些代码。包含在数组数组中的数组具有不同的长度(即SIZE2不是常数),这就是为什么我没有变平为一维数组。

此实施有什么问题?任何实现副本的想法?

EDIT2 : 我写的原始代码没问题。我编辑了代码以包含我所遇到的错误,并在下面包含了正确的答案(代码)。

1 个答案:

答案 0 :(得分:1)

错误在于我使用数组总大小getSize(i)作为分配和副本的索引。这是一个天真的错误,隐藏在真实代码的复杂性和冗长之中。

正确的解决方案是:

double** d_weights;
int init_cuda_weight(){
    cudaMalloc((void **) &d_weights, sizeof(double*) * SIZE);

    double** temp_d_ptrs = (double**) malloc(sizeof(double*) * SIZE);
    // temp array of device pointers
    for (int i = 0; i < SIZE; i++){
        cudaMalloc((void**) &temp_d_ptrs[i],
                sizeof(double) * getSize(i));
        // ERROR CHECK WITH cudaGetLastError()
        cudaMemcpy(temp_d_ptrs[i], weights[i], sizeof(double) * getSize(i), cudaMemcpyHostToDevice);
        // ERROR CHECK WITH cudaGetLastError()
    }

   cudaMemcpy(d_weights, temp_d_ptrs, sizeof(double*) * SIZE,
        cudaMemcpyHostToDevice);
}