コメントに示されているように、あなたのアプローチにはいくつかの問題があります。
- 特に初心者は、cuda 呼び出し (カーネル呼び出しを含む) で常にエラー チェックを行う必要があります。以下のコードは例です。または、この質問/回答を参照してください
- 最上位のポインターを cudaMalloc し、その下のポインターを cudaMalloc するというアプローチは機能しないため、cuda でポインターからポインターへの配置を作成することは直感的ではない場合があります。これは、その下のポインターを 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