私のGPUは何を待っていますか?


11

AMD Radeon HD 7800シリーズGPUで使用するOpenCLプログラムを書いています。AMDのOpenCLプログラミングガイドによると、この世代のGPUには、非同期で動作できる2つのハードウェアキューがあります。

5.5.6コマンドキュー

南部諸島以降では、デバイスは少なくとも2つのハードウェアコンピューティングキューをサポートします。これにより、アプリケーションは、非同期送信と場合によっては実行のための2つのコマンドキューを使用して、小さなディスパッチのスループットを向上させることができます。ハードウェアコンピューティングキューは、最初のキュー=偶数OCLコマンドキュー、2番目のキュー=奇数OCLキューの順に選択されます。

これを行うために、2つのOpenCLコマンドキューを作成して、データをGPUにフィードしました。おおまかに言って、ホストスレッドで実行されるプログラムは次のようになります。

static const int kNumQueues = 2;
cl_command_queue default_queue;
cl_command_queue work_queue[kNumQueues];

static const int N = 256;
cl_mem gl_buffers[N];
cl_event finish_events[N];

clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);

int queue_idx = 0;
for (int i = 0; i < N; ++i) {
  cl_command_queue queue = work_queue[queue_idx];

  cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);

  // Enqueue a few kernels
  cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);

  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);

  cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);

  clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);

  queue_idx = (queue_idx + 1) % kNumQueues;
}

clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);
clWaitForEvents(N, finish_events);

を使用するとkNumQueues = 1、このアプリケーションはほぼ意図したとおりに機能します。すべての作業が1つのコマンドキューに収集され、GPUが常にかなりビジー状態になるまで実行されます。CodeXLプロファイラーの出力を見ると、これを確認できます。

ここに画像の説明を入力してください

ただし、を設定kNumQueues = 2すると、同じことが起こると思いますが、作業は2つのキューに均等に分割されます。どちらかといえば、各キューは1つのキューと同じ特性を個別に持っていることを期待しています。ただし、2つのキューを使用すると、すべての作業が2つのハードウェアキューに分割されるわけではないことがわかります。

ここに画像の説明を入力してください

GPUの作業の開始時に、キューは一部のカーネルを非同期で実行することができますが、どちらもハードウェアキューを完全に占有しているようには見えません(私の理解が間違っていない限り)。GPU作業の終わり近くで、キューがハードウェアキューの1つだけに順次作業を追加しているように見えますが、カーネルが実行されていない場合もあります。何ができますか?ランタイムがどのように動作すると想定されているかについて、基本的な誤解がありますか?

これがなぜ起こっているのかについて私はいくつかの理論を持っています:

  1. 散在したclCreateBuffer呼び出しにより、GPUは共有メモリプールからデバイスリソースを同期的に割り当て、個々のカーネルの実行を停止させます。

  2. 基本的なOpenCL実装は、論理キューを物理キューにマップせず、実行時にオブジェクトを配置する場所を決定するだけです。

  3. 私はGLオブジェクトを使用しているため、GPUは書き込み中に特別に割り当てられたメモリへのアクセスを同期する必要があります。

これらの仮定のいずれかは真実ですか?2キューのシナリオでGPUが待機する原因を知っている人はいますか?どんな洞察もいただければ幸いです!


プログラミングガイドに2つのハードウェアキューがあると記載されている場所が見つかりません。文書からの引用を投稿できますか?キューが2つあると言っている章を挙げてください。OpenCLを使用してランタイムでクエリ可能なハードウェアキューの数はありますか?
Andreas

投稿を更新しました。それは実行の可能性を示していますが、それがいくつか実行できる場合、なぜすべて実行できないのでしょうか?また、OpenCLランタイムにはハードウェアキューの概念がないため、クエリできるものではありません。
Mokosha 2016年

回答:


2

一般に、計算キューは必ずしも2xディスパッチを並行して実行できることを意味するわけではありません。計算ユニットを完全に飽和させる単一のキューは、スループットが向上します。複数のキューは、1つのキューが消費するリソース(共有メモリまたはレジスタ)が少ない場合に役立ちます。その後、セカンダリキューが同じ計算ユニットでオーバーラップできます。

リアルタイムレンダリングの場合、これは特に、シャドウレンダリングなど、計算/シェーダーは非常に軽く、固定機能ハードウェアは重いため、GPUスケジューラーを解放してセカンダリキューを非同期で実行する場合に当てはまります。

これはリリースノートにも記載されています。それが同じ問題かどうかはわかりませんが、CodeXLが優れていない可能性があります。私は、ディスパッチが進行中の最良の計装を備えていない可能性があると思います。

https://developer.amd.com/wordpress/media/2013/02/AMD_CodeXL_Release_Notes.pdf

非同期データ転送とカーネル実行を同時に実行するアプリケーションの場合、アプリケーショントレースセッションビューに表示されるタイムラインには、これらの操作が重複して表示されません。これは、ドライバーとハードウェアがプロファイリング中にこれらの操作を強制的に同期させるためです。(333981)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.