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. 最上位のポインターを cudaMalloc し、その下のポインターを cudaMalloc するというアプローチは機能しないため、cuda でポインターからポインターへの配置を作成することは直感的ではない場合があります。これは、その下のポインターを 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 に答える