1

次のスレッドを既に読みましたが、コードを動作させることができませんでした。
GPU に 2D 配列を割り当て、値を入力して、CPU にコピーしようとしています。私のコードは次のとおりです。

__global__ void Kernel(char **result,int N)
{
    //do something like result[0][0]='a';
}
int N=20;
int Count=5;
char **result_h=(char**)malloc(sizeof(char*)*Count);
char **result_d; 
cudaMalloc(&result_d, sizeof(char*)*Count);
for(int i=0;i<Count;i++)
{
    result_h[i] = (char*)malloc(sizeof(char)*N);    
    cudaMalloc(&result_d[i], sizeof(char)*N); //get exception here
}

//call kernel
//copy values from result_d to result_h
printf("%c",result_h[0][0])//should print a

どうすればこれを達成できますか?

4

4 に答える 4

3

ホスト コードでデバイス ポインターを操作することはできません。これが、ループ内の cudaMalloc 呼び出しが失敗する理由です。おそらく、単一の連続したメモリ ブロックを割り当てて、それを平坦化された 2D 配列として扱う必要があります。

于 2011-03-30T19:19:05.303 に答える
1

GPU で最も単純な 2D 操作を実行するには、GPU を 1D 配列として扱うことをお勧めします。cudaMalloc サイズ w*h*sizeof(char) のブロック。インデックス j*w+i を介して要素 (i,j) にアクセスできます。

または、 cudaMallocArrayを使用して 2D 配列を取得することもできます。これは、線形にマップされた 2D メモリよりも局所性の感覚が優れています。たとえば、これをテクスチャに簡単にバインドできます。

あなたの例に関して言えば、それが機能しない理由は、 cudaMalloc がデバイスメモリのブロックを指すようにホストポインターを操作するためです。あなたの例では、デバイス上の results_d のポインター構造を割り当てました。results_d の cudaMalloc 呼び出しを通常の malloc に変更するだけで、当初の意図どおりに動作するはずです。

とはいえ、コードのメンテナンスを容易にするという観点からは、おそらく、上記で概説した 2 つのオプションのいずれかがより適切に機能する可能性があります。

于 2011-04-03T12:07:18.930 に答える
0

このように割り当てると、CPUメモリで有効なアドレスが割り当てられます。アドレスの値は問題なく数値として転送されますが、デバイスのメモリに入ると、char*アドレスには意味がありません。

N *最大テキスト長の配列と、各単語の長さを示す長さNの別の配列を作成します。

これはもう少し高度ですが、定義されたテキストのセット(パスワードなど)を処理している場合は、テキストの長さでグループ化し、長さごとに専用のカーネルを作成することをお勧めします

template<int text_width>
__global__ void Kernel(char *result,int N)
{
    //pseudocode
    for i in text_width:
        result[idx][i] = 'a'
}

カーネル呼び出しコードで指定するものは次のとおりです。

switch text_length
case 16:
   Kernel<16> <<<>>> ()
于 2011-03-30T20:48:16.337 に答える