0

私は 2 つのカーネルを使用してABます。

CUDA プロファイラーを実行すると、次のような結果が返されました。

ここに画像の説明を入力

最初のカーネルには 44% のオーバーヘッドがあり、2 番目のカーネルには 20% のオーバーヘッドがあります。

ただし、次のロジックに従って実際の実行時間を調べることにした場合:

timeval tim;
gettimeofday(&tim, NULL);
double before = tim.tv_sec+(tim.tv_usec/1000000.0);

runKernel<<<...>>>(...)

gettimeofday(&tim, NULL);
double after=tim.tv_sec+(tim.tv_usec/1000000.0);
totalTime = totalTime + after - before;

totalTime非常に小さく、約 0.0001 秒です。

私はCUDAが初めてで、何が起こっているのか正確にはわかりません。カーネルをより効率的にする必要がありますか、それともすでに効率的ですか?

4

1 に答える 1

3

カーネル呼び出しは、CPU の観点からは非同期です (この回答を参照してください)。同期を行わずに (つまり、 を呼び出さずにcudaDeviceSynchronize()) カーネルのタイミングを計った場合、計算は GPU でまだ進行中であるため、タイミングは何の意味も持ちません。

カーネルのタイミングに関しては、NVIDIA のプロファイラーを信頼できます ( nvprof/ nvvp)。NVIDIA Visual Profiler は、プログラムを分析し、カーネルの何が問題なのかについてアドバイスを提供することもできます:結合されていないメモリ アクセス、割り当てられたスレッド/ブロックの非効率的な数など。また、最適化フラグを使用してコードをリリース モードでコンパイルする必要があります。 (例-O3)関連するタイミングを取得します。

カーネルの最適化に関しては、ボトルネック (44% カーネルなど) を見つけて分析し、通常の最適化手法を適用する必要があります。

  • デバイスの有効な帯域幅を使用して、カーネルのパフォーマンスの上限を決定します
  • ホストとデバイス間のメモリ転送を最小限に抑えます - デバイス上で効率的でない計算を行うことを意味する場合でも
  • すべてのメモリ アクセスを結合する
  • グローバル メモリ アクセスよりも共有メモリ アクセスを優先する
  • これによりスレッドがシリアル化されるため、1 回のワープ内でのコード実行の分岐を回避します。

命令レベルの並列処理も使用できます (これらのスライドを読む必要があります)。

ただし、いつカーネルを最適化できなくなるかを知るのは困難です。カーネルの実行時間が短いと言っても、あまり意味がありません。何と比べて短いのでしょうか? リアルタイム計算をしようとしていますか?スケーラビリティは問題ですか?これらは、カーネルを最適化する前に答える必要のある質問の一部です。

補足として、エラー チェックをcuda-memcheck広範囲に使用し、 /に依存しcuda-gdbてコードをデバッグする必要もあります。

于 2013-05-15T12:41:52.863 に答える