6

2D配列をCudaに送信する方法を理解するのに少し問題があります。各行に30個のデータポイントがある大きなファイルを解析するプログラムがあります。一度に約10行を読み取り、各行とアイテムのマトリックスを作成します(したがって、30個のデータポイントを持つ10行の例では、int list[10][30]; この配列をカーネルに送信し、各ブロックに行(通常のCで完全に機能するようになりましたが、Cudaはもう少し挑戦的です)。

これが私がこれまでやってきたことですが、運がありません(注:sizeofbucket =行、sizeOfBucketsHoldings =行のアイテム...奇数の変数名で賞を獲得する必要があることはわかっています):

    int list[sizeOfBuckets][sizeOfBucketsHoldings]; //this is created at the start of the file and I can confirmed its filled with the correct data
#define sizeOfBuckets 10 //size of buckets before sending to process list
#define sizeOfBucketsHoldings  30
    //Cuda part
                //define device variables
                int *dev_current_list[sizeOfBuckets][sizeOfBucketsHoldings];
                //time to malloc the 2D array on device
                size_t pitch;
                cudaMallocPitch((int**)&dev_current_list,  (size_t *)&pitch, sizeOfBucketsHoldings * sizeof(int), sizeOfBuckets);

                //copy data from host to device
                cudaMemcpy2D( dev_current_list, pitch, list, sizeOfBuckets * sizeof(int), sizeOfBuckets * sizeof(int), sizeOfBucketsHoldings * sizeof(int),cudaMemcpyHostToDevice );

                process_list<<<count,1>>> (sizeOfBuckets, sizeOfBucketsHoldings, dev_current_list, pitch);
                //free memory of device
                cudaFree( dev_current_list );


    __global__ void process_list(int sizeOfBuckets, int sizeOfBucketsHoldings, int *current_list, int pitch) {
        int tid = blockIdx.x;
        for (int r = 0; r < sizeOfBuckets; ++r) {
            int* row = (int*)((char*)current_list + r * pitch);
            for (int c = 0; c < sizeOfBucketsHoldings; ++c) {
                 int element = row[c];
            }
        }

私が得ているエラーは次のとおりです。

main.cu(266): error: argument of type "int *(*)[30]" is incompatible with parameter of type "int *"
1 error detected in the compilation of "/tmp/tmpxft_00003f32_00000000-4_main.cpp1.ii".

266行目はカーネル呼び出しprocess_list<<<count,1>>> (count, countListItem, dev_current_list, pitch); です。問題は、関数内にint *として配列を作成しようとしていることだと思いますが、他にどのように作成できますか?私の純粋なCコードでは、これを使用int current_list[num_of_rows][num_items_in_row]していますが、Cudaで同じ結果を得ることができません。

私の最終目標は単純です。各ブロックに各行(sizeOfBuckets)を処理​​させてから、その行のすべてのアイテム(sizeOfBucketHoldings)をループさせたいだけです。私は元々通常のcudamallocとcudaMemcpyを実行しましたが、機能していなかったので、周りを見回して、MallocPitchと2dcopy(どちらも私のcuda by example本にはありませんでした)について調べました。私も同じエラーです(私は現在、CUDA_Cプログラミングガイドを読んでいますが、22ページでこのアイデアを見つけましたが、それでも運がありません)。何か案は?またはどこを見るべきかの提案?

編集:これをテストするには、各行の値を一緒に追加したいだけです(配列追加の例でcudaからロジックをコピーしました)。私のカーネル:

__global__ void process_list(int sizeOfBuckets, int sizeOfBucketsHoldings, int *current_list, size_t pitch, int *total) {
    //TODO: we need to flip the list as well
    int tid = blockIdx.x;
    for (int c = 0; c < sizeOfBucketsHoldings; ++c) {
        total[tid] = total + current_list[tid][c];
    }
}

メインで配列全体を宣言する方法は次のとおりです。

int *dev_total;
cudaMalloc( (void**)&dev_total, sizeOfBuckets * sizeof(int) );
4

1 に答える 1

5

コードにいくつかの間違いがあります。

  • 次に、ホスト配列をデバイスにコピーし、1 次元のホスト ポインターを渡す必要があります。関数のシグネチャを参照してください。
  • デバイス メモリに静的な 2D 配列を割り当てる必要はありません。ホストメモリに静的配列を作成し、デバイス配列として再作成します。それも一次元配列でなければならないことに注意してください。この関数シグネチャを参照してください。

この例は、メモリ割り当てに役立ちます。

__global__ void process_list(int sizeOfBucketsHoldings, int* total, int* current_list, int pitch)
{
    int tid = blockIdx.x;
    total[tid] = 0;
    for (int c = 0; c < sizeOfBucketsHoldings; ++c)
    {
        total[tid] += *((int*)((char*)current_list + tid * pitch) + c);
    }
}

int main()
{
    size_t sizeOfBuckets         = 10;
    size_t sizeOfBucketsHoldings = 30;

    size_t width = sizeOfBucketsHoldings * sizeof(int);//ned to be in bytes
    size_t height = sizeOfBuckets;

    int* list = new int [sizeOfBuckets * sizeOfBucketsHoldings];// one dimensional
    for (int i = 0; i < sizeOfBuckets; i++)
        for (int j = 0; j < sizeOfBucketsHoldings; j++)
            list[i *sizeOfBucketsHoldings + j] = i;

    size_t pitch_h = sizeOfBucketsHoldings * sizeof(int);// always in bytes

    int* dev_current_list;
    size_t pitch_d;
    cudaMallocPitch((int**)&dev_current_list, &pitch_d, width, height);

    int *test;
    cudaMalloc((void**)&test, sizeOfBuckets * sizeof(int));
    int* h_test = new int[sizeOfBuckets];

    cudaMemcpy2D(dev_current_list, pitch_d, list, pitch_h, width, height, cudaMemcpyHostToDevice);

    process_list<<<10, 1>>>(sizeOfBucketsHoldings, test, dev_current_list, pitch_d);
    cudaDeviceSynchronize();

    cudaMemcpy(h_test, test, sizeOfBuckets * sizeof(int), cudaMemcpyDeviceToHost);

    for (int i = 0; i < sizeOfBuckets; i++)
        printf("%d %d\n", i , h_test[i]);
    return 0;
}

カーネルで 2D 配列にアクセスするには、 pattern を使用する必要がありますbase_addr + y * pitch_d + x警告: ピットは常にバイト単位です。ポインタを にキャストする必要がありますbyte*

于 2012-06-22T04:52:17.670 に答える