4

私は単純なcudaプログラムに取り組んでいました.90%の時間は、デバイスからホストへのcudamemcpyである単一のステートメントから来ていることがわかりました。プログラムは、ホストからデバイスに 600 ~ 700 マイクロ秒で 2MB のデータを転送し、10ms でデバイスからホストに 4MB のデータをコピーしていました。私のプログラムにかかった合計時間は 13 ミリ秒でした。私の質問は、デバイスからホストへのコピーとホストからデバイスへのコピーの 2 つに非対称性があるのはなぜかということです。cuda の開発者が、コピーバックは通常バイト単位で小さくなると考えていたからでしょうか。私の2番目の質問は、それを回避する方法があるということです.

343 コアと 1GB メモリの Fermi GTX560 グラフィックス カードを使用しています。

4

1 に答える 1

2

CUDA 関数のタイミングは、CPU とは少し異なります。まず、アプリケーションの開始時に CUDA 関数を呼び出して CUDA の初期化コストを考慮しないようにしてください。そうしないと、タイミングを開始したときに初期化される可能性があります。

int main (int argc, char **argv) {
   cudaFree(0);
   ....//cuda is initialized..

}

このようにCutilタイマーを使用します

unsigned int timer;
cutCreateTimer(&timer);
cutStartTimer(timer);

//your code, to assess elapsed time..

cutStopTimer(timer);
printf("Elapsed: %.3f\n", cutGetTimerValue(timer));
cutDeleteTimer(timer);

さて、これらの準備手順の後、問題を見てみましょう。カーネルが呼び出されると、呼び出しが GPU に配信されるまで CPU 部分が停止します。CPU も継続している間、GPU は実行を継続します。cudaThreadSynchronize(..) を呼び出すと、CPU は GPU が現在の呼び出しを終了するまで停止します。cudaMemCopy 操作では、カーネルによって埋められるべき値が要求されるため、GPU がその実行を終了する必要もあります。

kernel<<<numBlocks, threadPerBlock>>>(...);

cudaError_t err = cudaThreadSynchronize();
if (cudaSuccess != err) {
  fprintf(stderr, "cudaCheckError() failed at %s:%i : %s.\n", __FILE__, __LINE__, cudaGetErrorString( err ) );
  exit(1);
}

//now the kernel is complete..
cutStopTimer(timer);

そのため、停止タイマー関数を呼び出す前に同期を配置します。カーネル呼び出しの後にメモリ コピーを配置すると、メモリ コピーの経過時間にはカーネル実行の一部が含まれます。そのため、タイミング操作の後に memCopy 操作を配置できます。

カーネルの一部のセクションを評価するために使用できるプロファイラー カウンターもいくつかあります。

cuda カーネルのグローバルメモリトランザクション数をプロファイリングする方法は?

CUDA カーネルのプロファイリングと最適化の方法

于 2012-09-02T16:23:39.130 に答える