-1

私は奇妙な問題を抱えているので、私より経験豊富な誰かが解決策を見つけることができるかどうか尋ねてみようと思いました。

私はCUDAC/ C ++でプログラムを書いていますが、計算の境界の座標など、さまざまなものを指定する定数整数がいくつかあります。現在、それらはグローバルデバイスメモリにあります。それらはすべてのカーネル呼び出しのすべてのスレッドによってアクセスされるので、それらがグローバルメモリにある場合、それらはキャッシュまたはブロードキャストされないことがわかりました(右?)。したがって、これらの小さな整数は(比較的)多くのオーバーヘッドを占めており、多くの「読み取りの冗長性」があります。

だから私はヘッダーで宣言します:

__constant__ int* number;

私はそのヘッダーを含めます、そして、私が記憶のことをするとき、私はします:

cutilSafeCall( cudaMemcpyToSymbol(number, &(some_host_int), sizeof(int) );

number次に、すべてのカーネルに渡します。

__global__ void magical_kernel(int* number, ...){

   //and I access 'number' like this
   int data_thingy = big_array[ *number ];

}

コードがクラッシュします。グローバルメモリに数値があるので、問題ありません。カーネル内の番号にアクセスすると、いつかクラッシュすることがわかりました。これは、アクセスしているか、割り当てが間違っていることを意味します。間違った値を保持していると、配列へのインデックス作成に使用されるため、クラッシュも発生します。

結論として、私はいくつかの質問をします。まず、私は何が間違っているのですか?numberボーナスとして:このタスクを実行するための一定のメモリよりも優れた方法はありますか?コンパイル時の値がわからないため、単純な#defineは機能しません。コンスタントメモリはコードをまったく高速化しますか、それともキャッシュされてずっとブロードキャストされていますか?どういうわけか、各スレッドブロックの共有メモリにデータを入れて、複数のカーネル呼び出しを通じて共有メモリに残しておくことができますか?

4

1 に答える 1

1

ここにはいくつかの問題があります。

  1. ポインタとして宣言numberしましたが、GPUメモリ内の有効なアドレスである値を割り当てたことはありません
  2. 変数スコープonflictがあります。で定義された引数変数int * numberは、コンパイル単位スコープとして定義されたmagic_kernel 変数と同じではありません。__constant__ int * variable
  3. 呼び出しの最初の引数cudaMemcpyToSymbolはほぼ間違いなく正しくありません。

最初の2つのポイントのいずれかが当てはまる理由がわからない場合は、C++のポインターとスコープに対して行うべき修正があります。

削除された回答に対するあなたの回答に基づいて、あなたが実際にやろうとしていることはこれだと思います。

__constant__ int number;

__global__ void magical_kernel(...){

   int data_thingy = big_array[ number ];

}

cudaMemcpyToSymbol("number", &(some_host_int), sizeof(int));

つまりnumber、定数メモリ内の整数であり、ポインタではなく、カーネル引数ではないことを目的としています。


編集:これは実際にこれを示す例です:

#include <cstdio>

__constant__ int number;

__global__ void magical_kernel(int * out)
{
   out[threadIdx.x] = number;
}

int main()
{
    const int value = 314159;
    const size_t sz = size_t(32) * sizeof(int);
    cudaMemcpyToSymbol("number", &value, sizeof(int));

    int * _out, * out;

    out = (int *)malloc(sz);
    cudaMalloc((void **)&_out, sz);

    magical_kernel<<<1,32>>>(_out);

    cudaMemcpy(out, _out, sz, cudaMemcpyDeviceToHost);
    for(int i=0; i<32; i++)
        fprintf(stdout, "%d %d\n", i, out[i]);

    return 0;
}

これを自分で実行して、宣伝どおりに機能することを確認できるはずです。

于 2012-06-17T06:52:35.557 に答える