如评论中所示,您的方法存在几个问题。
- 特别是作为初学者,您应该始终对您的 cuda 调用(包括内核调用)进行错误检查。在我下面的代码中是一个例子,或者参考这个问题/答案
- 在 cuda 中创建指针到指针的排列有时并不直观,因为 cudaMalloc'ing 顶级指针然后 cudaMalloc'ing 其下方的指针的方法将不起作用。这是因为要将其下方的指针传递给 cudaMalloc,我们必须将顶层指针传递给 cudaMalloc,但这已经是一个设备指针。cudaMalloc 希望您传递一个主机指针,然后 cudaMalloc 将位于设备上。因此,为了解决这个问题,通常需要在主机上创建影子或并行指针排列,并将所有这些依次传递给 cudaMalloc,然后将这些指针复制到设备。有关示例,请参见下面的代码。
- 您还想测试主机上设备指针的有效性,看看您是否需要 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