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つだけに順次作業を追加しているように見えますが、カーネルが実行されていない場合もあります。何ができますか?ランタイムがどのように動作すると想定されているかについて、基本的な誤解がありますか?
これがなぜ起こっているのかについて私はいくつかの理論を持っています:
散在した
clCreateBuffer
呼び出しにより、GPUは共有メモリプールからデバイスリソースを同期的に割り当て、個々のカーネルの実行を停止させます。基本的なOpenCL実装は、論理キューを物理キューにマップせず、実行時にオブジェクトを配置する場所を決定するだけです。
私はGLオブジェクトを使用しているため、GPUは書き込み中に特別に割り当てられたメモリへのアクセスを同期する必要があります。
これらの仮定のいずれかは真実ですか?2キューのシナリオでGPUが待機する原因を知っている人はいますか?どんな洞察もいただければ幸いです!