0

我是 CUDA 的新手。我想将一堆图像复制到设备上。

unsigned char** _devStackImagesCuda = NULL;
int stackSize = 5;//should be replaced by argument to the function
if(_devStackImagesCuda == NULL)\\allocate array of pointers on the device
{
    cudaMalloc(&_devStackImagesCuda,  sizeof(unsigned char*)  * stackSize);
    cudaMemset(_devStackImagesCuda, 0, sizeof(unsigned char*) * stackSize);
}

for(int i = 0; i < stackSize; i++)
{

    if(_devStackImagesCuda[i] == NULL) //allocates one image on the device.
        cudaMalloc(&_devStackImagesCuda[i], imageSize * sizeof(unsigned char));
    cudaMemcpy(_devStackImagesCuda[i], _imageStack->GetImage(i, dummy, true), imageSize, cudaMemcpyHostToDevice);//copy image data to device
}

可以吗?

4

1 回答 1

2

如评论中所示,您的方法存在几个问题。

  1. 特别是作为初学者,您应该始终对您的 cuda 调用(包括内核调用)进行错误检查。在我下面的代码中是一个例子,或者参考这个问题/答案
  2. 在 cuda 中创建指针到指针的排列有时并不直观,因为 cudaMalloc'ing 顶级指针然后 cudaMalloc'ing 其下方的指针的方法将不起作用。这是因为要将其下方的指针传递给 cudaMalloc,我们必须将顶层指针传递给 cudaMalloc,但这已经是一个设备指针。cudaMalloc 希望您传递一个主机指针,然后 cudaMalloc 将位于设备上。因此,为了解决这个问题,通常需要在主机上创建影子或并行指针排列,并将所有这些依次传递给 cudaMalloc,然后将这些指针复制到设备。有关示例,请参见下面的代码。
  3. 您还想测试主机上设备指针的有效性,看看您是否需要 cudaMalloc 它。这不起作用,因为它会导致取消引用主机上的设备指针。特别是在这一行:if(_devStackImagesCuda[i] == NULL),您正在尝试查看 _devStackImagesCuda[i] 是否有效,但为了做到这一点,您必须取消引用,_devStackImagesCuda但是您之前已经对此指针(指向指针)执行了 cudaMalloc,因此它现在是一个设备指针,不允许在主机上取消引用。我建议您跟踪是否需要以其他方式对这些指针进行 cudaMalloc。

我相信这样的事情会奏效:

#include <stdio.h>

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)


int main(){

  unsigned char ** _devStackImagesCuda=0;

  int stackSize = 5;
  int imageSize = 4;
  unsigned char *temp[stackSize];
  unsigned char dummy_image[imageSize];
// first create top level pointer
  if ( _devStackImagesCuda == 0) //allocate array of pointers on the device
    {
    cudaMalloc(&_devStackImagesCuda,  sizeof(unsigned char*)  * stackSize);
    cudaCheckErrors("cm 1");
    }
// then create child pointers on host, and copy to device, then copy image
  for(int i = 0; i < stackSize; i++)
    {

    cudaMalloc(&temp[i], imageSize * sizeof(unsigned char));
    cudaCheckErrors("cm 2");
    cudaMemcpy(&(_devStackImagesCuda[i]), &(temp[i]), sizeof(unsigned char *), cudaMemcpyHostToDevice);//copy child pointer to device
    cudaCheckErrors("cudamemcopy1");
    cudaMemcpy(temp[i], dummy_image, imageSize*sizeof(unsigned char), cudaMemcpyHostToDevice); // copy image to device
    cudaCheckErrors("cudamemcpy2");

    }


return 0;
}

顺便说一句,如果您可以将图像数组视为连续区域,则可以大大简化事情。像这样:

unsigned char images[NUM_IMAGES*IMAGE_SIZE]; // or you could malloc this
unsigned char *d_images;
cudaMalloc((void **) d_images, NUM_IMAGES*IMAGE_SIZE*sizeof(unsigned char));
cudaMemcpy(d_images, images, NUM_IMAGES*IMAGE_SIZE*sizeof(unsigned char), cudaMemcpyHostToDevice);

并通过以下方式访问单个图像元素:

unsigned char mypixel = images[i + (IMAGE_SIZE * j)]; // to access element i in image j
于 2013-02-27T15:02:54.910 回答