0

似たような質問を検索してみましたが、似たようなタイトルの質問がいくつかありますが、見つかりませんでした。

ホストに次のようなコードがあります。

handle_error(cudaMalloc((void**)&ret_dev, FLOAT_SIZE*no_kstrings*M));
for(int div=0;div<no_kstrings/threads;div++){
   kernel<<<grid_dim,block_dim>>>(ret_dev, v_freq_vectors, &no_kstrings[threads]);
   handle_error(cudaMemcpy(&exp_freq[threads], ret_dev, FLOAT_SIZE*threads*M, 
        cudaMemcpyDeviceToHost));
}

基本的に、ループ内のコードを最大数の倍数として実行する必要があります。ブロックあたりのスレッド数。そして、カーネル関数は単に何かを行い、データを に入れますret_dev。だから私は疑問に思っていcudaMemcpy()ました、各反復の後に行う必要がありますか、それともループの外でも行うことができますか? このようなもの:

handle_error(cudaMalloc((void**)&ret_dev, FLOAT_SIZE*no_kstrings*M));
for(int div=0;div<no_kstrings/threads;div++){
   kernel<<<grid_dim,block_dim>>>(ret_dev, v_freq_vectors, &no_kstrings[threads]);
}
handle_error(cudaMemcpy(exp_freq, ret_dev, FLOAT_SIZE*no_kstrings*M, 
     cudaMemcpyDeviceToHost));

私が聞きたいのは、同じ引数でカーネル関数を複数回呼び出すと、それらの引数が何らかの形で破損するのでしょうか?

ありがとう

4

1 に答える 1

0

ストリームを指定せずにカーネルを複数回 (または複数のカーネルを) 起動すると、それらは標準ストリーム 0 でキューに入れられ、連続して実行されます。memcpy 呼び出しについても同じアカウントです。これらのカーネルと memcpy 呼び出しの順序は保持されます。また、カーネル引数は常に値で渡され、後で値を変更しても、まだ起動されていなくても、既にスケジュールされている呼び出しが破損することはありません。

あなたのケースで memcpy をループの外に移動できるかどうかは、カーネルが何をするかによって異なります。すべてのカーネルが独自のデータ チャンクで動作する場合は、すべてのカーネルを起動した後に結果をコピーしても問題ありません。その場合、アルゴリズムにグローバル同期が必要かどうかを確認することをお勧めします。そうでない場合は、for ループをカーネル内に移動することで速度を大幅に向上させることができるからです。

カーネルがすべてのデータで動作し、特定の時間に保存する必要がある場合でも、gpu に追加の結果配列を割り当てて、カーネル内にコピーすることを検討できます。これは、ループ内で memcpy を実行するよりもはるかに高速です。

于 2013-02-08T14:24:23.323 に答える