0

cudaで2次元配列を作成して初期化しようとしていますが、惨めに失敗しています。これが私の初期化カーネルです:

__global__ void initMap(float* map, size_t pitch, int w, int h, int numX, int numY){
int idx=blockIdx.x*blockDim.x+threadIdx.x;
int idy=blockIdx.y*blockDim.y;
int i;
int j;
for (i=0; i<numX; i++){
    for (j=0; j<numY; j++){
        int idMC=idx+i;
        int idMR=threadIdx.y+j;
        if(idMC<w && idy+idMR<h){
             float* row=(float*)(map+idy+idMR*pitch);
             row[idMC]=0.5;
        }
    }
}

__syncthreads();
}

そして、配列を割り当て、メインで初期化カーネルを呼び出す方法は次のとおりです。

int width=map_size;
int height=map_size;
float* map;
size_t pitch;
checkCudaErrors(cudaMallocPitch(&map, &pitch, width*sizeof(float), height));
int numT=32;
int numBX=(int)ceil((float)width/numT);
int numBY=(int)ceil((float)height/numT);
dim3 numBlocks(numBX, numBY);
dim3 numThr(numT, numT);
initMap <<<numBlocks, numThr>>> (map, pitch/sizeof(float), width, height, 1, 1);
cudaError_t err=cudaGetLastError();
if (err != cudaSuccess) 
    printf("Error: %s\n", cudaGetErrorString(err));
checkCudaErrors(cudaDeviceSynchronize());

基本的に、私がやろうとしているのは、2D 配列を 32x32 のチャンクに分割し、それらのそれぞれをブロックに割り当てて、それを 0.5 で埋めることです。ただし、配列をディスクに書き込もうとしたり、別のカーネルからその要素にアクセスしようとしたりすると、そこに多くの QNAN があることがわかります。そのため、配列全体を埋めているのではなく、いくつかのスポットを見逃していると思います。

4

1 に答える 1

1

このようなものが動作するはずです:

__global__ void initMap(float* map, size_t pitch, int w, int h, int numX, int numY){
  int col = threadIdx.x + (blockDim.x * blockIdx.x);
  int row = threadIdx.y + (blockDim.y * blockIdx.y);

  if ((row < h) && (col < w)){
    float *myrow = (float *)(((char *)map)+(row*pitch));
    myrow[col] = 0.5f;
}

これは、パラメーターがバイトpitch数として渡されることを前提としています。これは、パラメーターを設定する方法です。したがって、最初に行う必要があるのは、ポインターへの変換です。次に、選択した行に基づいて適切なピッチ オフセットを追加し、結果のポインターをポインターに変換します。次に、ポインターを使用して、選択した行にインデックスを付けます。cudaMallocPitchmapcharfloatfloat

したがって、カーネル呼び出しを次のように調整する必要があります。

initMap <<<numBlocks, numThr>>> (map, pitch, width, height, 1, 1);

行よりも大きいインデックスにある「ファントム」要素はw、これによって初期化されないことに注意してください。それらにはゴミが含まれます。しかし、とにかくそれらの要素を使用したり、使用したりすることについて心配する必要はありません。

この配列をホストにコピーして戻す場合はcudaMemcpy2D、 を使用する必要があります。適切に設定されていれば、ホストへのコピー プロセス中にファントム要素が削除されるため、ホスト配列にガベージ データが存在することはありません。cudaMallocPitch/cudaMemcpy2D を適切に使用する方法を示す SO に関する質問がいくつかあります。

于 2014-02-15T18:23:40.733 に答える