Memory management CUDA分配数组的数组

Memory management CUDA分配数组的数组,memory-management,cuda,allocation,Memory Management,Cuda,Allocation,我在CUDA中分配数组时遇到一些问题 void ** data; cudaMalloc(&data, sizeof(void**)*N); // allocates without problems for(int i = 0; i < N; i++) { cudaMalloc(data + i, getSize(i) * sizeof(void*)); // seg fault is thrown } void**数据; cudaMalloc(&data,sizeof(

我在CUDA中分配数组时遇到一些问题

void ** data;
cudaMalloc(&data, sizeof(void**)*N); // allocates without problems
for(int i = 0; i < N; i++) {
    cudaMalloc(data + i, getSize(i) * sizeof(void*)); // seg fault is thrown
}
void**数据;
cudaMalloc(&data,sizeof(void**)*N);//分配没有问题
对于(int i=0;i

我做错了什么?

我认为这不受支持
cudamaloc()
分配设备内存,但将地址存储在主机上的变量中。在for循环中,您正在设备内存中传递它的地址

根据您试图完成的任务,您可能希望在调用for循环之前,使用普通主机
malloc()
分配
数据。或者分配一大块设备内存并手动计算偏移量

有关这方面的更多讨论,请参阅的第2.4节、第3.2.1节和第B.2.5节(底部)。具体而言,在第108页底部:

通过获取
\uuuu设备
\uuuu共享
\uuuu常量\uuuu
变量只能在设备代码中使用


您必须将指针分配给主机内存,然后为每个数组分配设备内存,并将其指针存储在主机内存中。 然后分配内存以将指针存储到设备中 然后将主机内存复制到设备内存。 一个例子胜过1000个字:

__global__ void multi_array_kernel( int N, void** arrays ){
    // stuff
}


int main(){

    const int N_ARRAYS = 20;
    void *h_array = malloc(sizeof(void*) * N_ARRAYS);
    for(int i = 0; i < N_ARRAYS; i++){
        cudaMalloc(&h_array[i], i * sizeof(void*));
        //TODO: check error
    }
    void *d_array = cudaMalloc(sizeof(void*) * N_ARRAYS);

    // Copy to device Memory
    cudaMemcpy(d_array, h_array, sizeof(void*) * N_ARRAYS, cudaMemcpyHostToDevice);

    multi_array_kernel<1,1>(N_ARRAYS, d_array);
    cudaThreadSynchronize();

    for(int i = 0; i < N_ARRAYS; i++){
        cudaFree(h_array[i]); //host not device memory
        //TODO: check error
    }
    cudaFree(d_array);
    free(h_array);
}
\uuuuu全局\uuuuu无效多数组\u内核(int N,void**array){
//东西
}
int main(){
常数int N_数组=20;
void*h_数组=malloc(sizeof(void*)*N_数组);
对于(int i=0;i
我认为在第一个循环中,它应该是
&h\u数组[I]
而不是
&d\u数组[I]

您不能使用

cudaMalloc(&h_array[i], i * sizeof(void*));
对于声明为
void*

cudaMalloc((void *)&h_array[i], i * sizeof(void*));
使用定义的数据类型

CUdeviceptr *h_array = malloc(sizeof(CUdeviceptr *) * N);

并将其强制转换为
void*

cudaMalloc((void *)&h_array[i], i * sizeof(void*));

我也有同样的问题,并设法解决了它

法布里齐奥的回答对我来说是一个很好的开始,对我帮助很大。但是,当我试图将代码转移到我的项目中时,我遇到了一些问题。使用附加的评论和帖子,我能够编写一个工作示例(VS2012,CUDA7.5)。因此,我将把我的代码作为附加答案和其他人的起点发布

为了理解命名:我使用OpenCV::Mat的向量作为输入,这些向量是从多个摄像头捕获的,我在内核中处理这些图像

     void TransferCameraImageToCuda(const std::vector<cv::Mat*>* Images)
{

     int NumberCams     = Images->size();
     int imageSize      = Images->at(0)->cols*Images->at(0)->rows;

     CUdeviceptr*           CamArraysAdressOnDevice_H;
     CUdeviceptr*           CamArraysAdressOnDevice_D;


         //allocate memory on host to store the device-address of each array
         CamArraysAdressOnDevice_H = new CUdeviceptr[NumberCams];

         // allocate memory on the device and store the arrays on the device 
         for (int i = 0; i < NumberCams; i++){
             cudaMalloc((void**)&(CamArraysAdressOnDevice_H[i]), imageSize * sizeof(unsigned short));
             cudaMemcpy((void*)CamArraysAdressOnDevice_H[i], Images->at(i)->data, imageSize * sizeof(unsigned short), cudaMemcpyHostToDevice);
         }

         // allocate memory on the device to store the device-adresses of the arrays
         cudaMalloc((void**)&CamArraysAdressOnDevice_D, sizeof(CUdeviceptr*)* NumberCams);

         // Copy the adress of each device array to the device
         cudaMemcpy(CamArraysAdressOnDevice_D, CamArraysAdressOnDevice_H, sizeof(CUdeviceptr*)* NumberCams, cudaMemcpyHostToDevice);




}

主要的一点是,所有这些数组的大小都不同。这是正确的。cudaMalloc分配的指针必须驻留在主机内存中,并且您正在尝试将这些指针存储在设备内存中。相反,您应该在主机上创建一个指针数组,然后将其复制到终端设备,或者按照Gabriel的建议计算偏移量。我猜您的意思是N_数组,而不是主函数中的N
DummyKernel<<<gridDim,blockDim>>>(NumberCams, (unsigned short**) CamArraysAdressOnDevice_D)
__global__ void DummyKernel(int NumberImages, unsigned short** CamImages)
{
    int someIndex = 3458;
    printf("Value Image 0 : %d \n", CamImages[0][someIndex]);
    printf("Value Image 1 : %d \n", CamImages[1][someIndex]);
    printf("Value Image 2 : %d \n", CamImages[2][someIndex]);
}