0

ここに私のCUDAコードがあります:

#include<stdio.h>
#include<assert.h>
void verify(float * A, float * B, int size);

__global__ void CopyData(float *d_array, float* d_dest_array, size_t pitch, int cols, int rows)
{
  for(int i=0; i<rows; i++){
        float *rowData = (float*)(((char*)d_array) + (i*pitch));
        for(int j=0; j<cols; j++){
            d_dest_array[i*cols+j] = *(rowData+j);
        }
    }
}

int main(int argc, char **argv)
{
    int row, col, i, j; 
    float time1, time2;
    float *d_array;                 // dev arr which mem will be alloc to
    float *d_dest_array;        // dev arr that will be a copy
    size_t pitch;                       // ensures correct data struc alignm    
    if(argc != 3)
  {
        printf("Usage: %s [row] [col]\n", argv[0]);
        return 1;
  }

    row = atoi(argv[1]);
    col = atoi(argv[2]);
    float *h1_array = new float[col*row];
    float *h2_array = new float[col*row];
    float *h_ori_array = new float[col*row];
    for (i = 0; i<row; i++){
        for(j = 0; j<col; j++){
            h_ori_array[i*col+j] = i*col + j;
        }
    }
    cudaEvent_t start, stop;

    cudaMallocPitch(&d_array, &pitch, col*sizeof(float), row);
    cudaMalloc(&d_dest_array, col*row*sizeof(float));
    cudaMemcpy2D(d_array, pitch, h_ori_array, col*sizeof(float), col*sizeof(float), row, cudaMemcpyHostToDevice);
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);
    //CopyData<<<100, 512>>>(d_array, d_dest_array, pitch, col, row);
    for (i = 0; i<row; i++){
        for(j = 0; j<col; j++){
            h1_array[i*col+j] = h_ori_array[i*col+j];
        }
    }
    cudaEventRecord(stop, 0);
    cudaEventSynchronize(stop);
    cudaEventElapsedTime(&time1, start, stop);

    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);
    CopyData<<<row*col/512, 512>>>(d_array, d_dest_array, pitch, col, row);
    cudaEventRecord(stop, 0);
    cudaEventSynchronize(stop);
    cudaEventElapsedTime(&time2, start, stop);

    cudaMemcpy2D(h2_array, pitch, d_dest_array, col*sizeof(float), col*sizeof(float), row, cudaMemcpyDeviceToHost);

    verify(h1_array, h2_array, row*col);

    free(h1_array); free(h2_array); free(h_ori_array);
  cudaFree(d_array); cudaFree(d_dest_array);
    printf("Exec time in ser = %f, par = %f ms with pitch %d", time1, time2, (int)pitch); 

    return 0;
}

void verify(float * A, float * B, int size)
{
    for (int i = 0; i < size; i++)
    {
        assert(A[i]==B[i]);
    }
     printf("Correct!");
}

マトリックスのコピーを作成するだけです。比較できるように、シリアル版とパラレル版の両方が書かれています。

配列サイズが 64 の場合は不正解、256 以上の場合は正解になります。ただし、512x512 マトリックスの場合は 4 秒と、時間がかかりすぎます。

私は cudaMemcpy2D に慣れていません。誰かが私が間違っていることを特定できますか? CUDA コーディング プラクティスに関する提案も歓迎します。 また、カーネルを呼び出すときに、ブロックとグリッドの次元を決定するにはどうすればよいですか?

編集 1: 私が使用した CopyData 関数は、並列処理を使用しません。ページの下部にある VIHARRI の回答から愚かにもコピーしました。

そこで選択された回答は、データがホストからデバイスにコピーされた方法を指定していません。cudaMallocPitch および cudaMemcpy2D 関数を使用してそれを行う方法を誰かが示すことができますか? カーネル内でインデックスを作成する正しい方法と、ホストからデバイスに 2D 配列をコピーする正しい方法を探しています。

4

1 に答える 1

1

実行している CUDA スレッドは 1 つだけです。(実際によく調べてみると、同じコードを複数のスレッドで実行していますが、結果は同じです。実際には GPU ハードウェアを活用していません)。

理想的には、最高のパフォーマンスを得るには、数百または数千の同時スレッドを実行する必要があります。これを行う 1 つの方法は、出力要素ごとに 1 つのスレッドを作成し、各スレッドでグリッド、ブロック、およびスレッド ID を使用して、処理する出力要素を決定することです。CUDA SDK の例を見て、CUDA による並列処理の一般的なパターンを理解してください。

于 2013-05-24T09:42:47.987 に答える