0

こんにちは、現在、CUDA コードの一部のタイミングを計っています。イベントを使用してそれらの時間を計ることができました。私のカーネルは 19 ミリ秒実行されました。これをシーケンシャルに実装したときは約 5000 ミリ秒だったので、どういうわけかこれは疑わしいと思います。コードがより速く実行される必要があることはわかっていますが、これほど高速である必要がありますか?

cpp プログラムでラッパー関数を使用して cuda カーネルを呼び出しています。そこで、または.cuファイルでそれらを呼び出すことになっていますか? ありがとう!

4

3 に答える 3

1

プログラムが機能しているかどうかを確認する明白な方法は、出力を CPU ベースの実装の出力と比較することです。同じ出力が得られた場合、それは定義上機能していますよね? :)

プログラムが実験的で、検証可能な出力が実際には生成されない場合、コンパイラがコードの一部 (またはすべて) を最適化した可能性が高くなります。コンパイラは、出力データに寄与しないコードを削除します。これにより、たとえば、計算された値を格納する最後のステートメントがコメントアウトされている場合、カーネルの内容全体が削除される可能性があります。

あなたのスピードアップについて。5000 ミリ秒 / 19 ミリ秒 = 263 倍であり、GPU アーキテクチャに完全に対応するアルゴリズムであっても、これはありそうもない増加です。

于 2012-06-18T02:31:51.527 に答える
0

ええと、あなたがあなたのCUDAコードを正しく書いたなら、そうです、それははるかに速いかもしれません。考えてみてください。GPUモデルに応じて、コードを単一のプロセッサでの順次実行から数百のプロセッサでの並列実行に移動しました。私の179ドルのミッドレンジカードには480コアがあります。現在利用可能なものの中には1500コアがあります。特にカーネルがメモリバウンドよりもはるかにコンピューティングバウンドである場合、CUDAで100倍のパフォーマンスジャンプを取得することは非常に可能です。

そうは言っても、自分が測定していると思うものを測定していることを確認してください。明示的なストリームを使用せずにCUDAカーネルを呼び出す場合、呼び出しはホストスレッドと同期しており、タイミングは正確である必要があります。ストリームを使用してカーネルを呼び出す場合は、cudaDeviceSynchronise()を呼び出すか、カーネルによって通知されたイベントをホストコードで待機させる必要があります。ストリームで呼び出されたカーネル呼び出しはホストスレッドに対して非同期で実行されるため、カーネル呼び出しが完了するまでホストスレッドを待機させない限り、ホストスレッドでの時間測定はカーネル時間を正しく反映しません。CUDAイベントを使用して、特定のストリーム内のGPUの経過時間を測定することもできます。NVidia GPU ComputingSDK4.2のCUDAベストプラクティスガイドのセクション5.1.2を参照してください。

于 2012-06-18T06:08:51.377 に答える
-3

私自身のコードでは、このclock()関数を使用して正確なタイミングを取得しています。便宜上、私はマクロを持っています

enum {
    tid_this = 0,
    tid_that,
    tid_count
    };
__device__ float cuda_timers[ tid_count ];
#ifdef USETIMERS
 #define TIMER_TIC clock_t tic; if ( threadIdx.x == 0 ) tic = clock();
 #define TIMER_TOC(tid) clock_t toc = clock(); if ( threadIdx.x == 0 ) atomicAdd( &cuda_timers[tid] , ( toc > tic ) ? (toc - tic) : ( toc + (0xffffffff - tic) ) );
#else
 #define TIMER_TIC
 #define TIMER_TOC(tid)
#endif

次に、これらを使用して、次のようにデバイス コードをインストルメント化できます。

__global__ mykernel ( ... ) {

    /* Start the timer. */
    TIMER_TIC

    /* Do stuff. */
    ...

    /* Stop the timer and store the results to the "timer_this" counter. */
    TIMER_TOC( tid_this );

    }

cuda_timersその後、ホスト コードでを読み取ることができます。

いくつかのメモ:

  • タイマーはブロック単位で動作します。つまり、同じカーネルを実行する 100 個のブロックがある場合、すべての時間の合計が保存されます。
  • タイマーは、クロック ティックの数をカウントします。ミリ秒数を取得するには、これをデバイスの GHz 数で割り、1000 を掛けます。
  • タイマーはコードの速度を少し遅くする可能性がある#ifdef USETIMERSため、簡単にオフにできるように でラップしました。
  • clock()タイプ の整数値を返しますが、clock_t累積値を として保存しますfloat。そうしないと、数秒以上かかるカーネルの値がラップアラウンドします (すべてのブロックで累積されます)。
  • ( toc > tic ) ? (toc - tic) : ( toc + (0xffffffff - tic) ) )クロックカウンタがラップアラウンドする場合に備えて選択が必要です。
于 2012-06-17T10:50:35.427 に答える