10

ここ数日間、答えのない質問が宙に浮いています。同じ問題の OpenMP と OpenCL の実装があるため、質問が発生しました。OpenCL は GPU 上で完全に実行されますが、CPU 上で実行するとパフォーマンスが 50% 低下します (OpenMP 実装と比較して)。OpenMP と OpenCLのパフォーマンスの違いについては既に投稿されていますが、私の質問には答えていません。現時点では、次の質問に直面しています。

1) 「ベクトル化されたカーネル」(Intel Offline Compiler に関して)を持つことは本当に重要ですか?

同様の投稿がありますが、私の質問はより一般的だと思います。

私が理解しているように、ベクトル化されたカーネルは、コンパイルされたバイナリにベクトル/SIMD 命令がないことを必ずしも意味しません。カーネルのアセンブリ コードを確認したところ、SIMD 命令がたくさんありました。ベクトル化されたカーネルとは、SIMD 命令を使用することで、1 つの CPU スレッドで 4 つ (SSE) または 8 つ (AVX) の OpenCL "論理" スレッドを実行できることを意味します。これは、すべてのデータがメモリに連続して保存されている場合にのみ実現できます。しかし、誰がそのように完全にソートされたデータを持っているでしょうか?

私の質問は次のとおりです。この意味で、カーネルを「ベクトル化」することは本当に重要ですか?

もちろん、パフォーマンスは向上しますが、カーネル内の計算集約的な部分のほとんどがベクトル命令によって実行される場合、「最適な」パフォーマンスに近づく可能性があります。私の質問に対する答えは、メモリ帯域幅にあると思います。おそらく、効率的なメモリアクセスにはベクトルレジスタの方が適しています。その場合、カーネル引数 (ポインター) をベクトル化する必要があります。

2) CPUのローカル メモリにデータを割り当てると、どこに割り当てられますか? OpenCL は L1 キャッシュをローカル メモリとして表示しますが、明らかに GPU のローカル メモリと同じタイプのメモリではありません。RAM /グローバルメモリに保存されている場合、データをそこにコピーしても意味がありません。それがキャッシュにある場合、他のプロセスがそれをフラッシュする可能性があります...したがって、それも意味がありません。

3) 「論理的な」OpenCL スレッドは、実際の CPU ソフトウェア/ハードウェア (Intel HTT) スレッドにどのようにマップされますか? 実行時間が短いカーネルがあり、カーネルが TBB (スレッド ビルディング ブロック) や OpenMP のようにフォークされている場合、フォークのオーバーヘッドが支配的になります。

4) スレッドフォークのオーバーヘッドは? 「論理的な」OpenCL スレッドごとにフォークされた新しい CPU スレッドがありますか、それとも CPU スレッドが一度フォークされ、より多くの「論理的な」OpenCL スレッドに再利用されますか?

これらの小さなことに興味を持っているのは私だけではないと思います. 前もって感謝します!


アップデート

3) 現時点では、OpenCL のオーバーヘッドは OpenMP よりも大きいため、ランタイムを効率的に実行するには重いカーネルが必要です。Intel OpenCL では、ワークグループが TBB スレッドにマップされるため、1 つの仮想 CPU コアがワークグループ全体 (またはスレッドブロック) を実行します。ワークグループは 3 つのネストされた for ループで実装され、可能であれば最も内側のループがベクトル化されます。したがって、次のように想像できます。

#pragam omp parallel for
for(wg=0; wg < get_num_groups(2)*get_num_groups(1)*get_num_groups(0); wg++) {

  for(k=0; k<get_local_size(2); k++) {
    for(j=0; j<get_local_size(1); j++) {
      #pragma simd
      for(i=0; i<get_local_size(0); i++) {
        ... work-load...
      }
    }
  }
}

最も内側のループをベクトル化できる場合、SIMD ステップで進みます。

for(i=0; i<get_local_size(0); i+=SIMD) {

4) すべての TBB スレッドは、OpenCL の実行中に 1 回フォークされ、再利用されます。すべての TBB スレッドは、仮想コアに関連付けられています。計算中にスレッドの移行はありません。

@natchouf-s の回答も受け付けます。

4

2 に答える 2

8

あなたの質問にいくつかのヒントがあるかもしれません。私のわずかな経験では、CPU 向けに調整された優れた OpenCL 実装は、優れた OpenMP 実装に勝るものはありません。もしそうなら、おそらく OpenMP コードを改善して OpenCL コードを打ち負かすことができます。

1)ベクトル化されたカーネルを持つことは非常に重要です。質問番号 3 と 4 にリンクされています。4 つまたは 8 つの入力値を処理するカーネルを使用している場合、作業項目 (スレッド) がはるかに少なくなるため、オーバーヘッドがはるかに少なくなります。自動ベクトル化に頼るのではなく、 OpenCL が提供するベクトル命令とデータ ( float4、 float8 、float16など) を使用することをお勧めします。float16 (またはdouble16 )を使用することを躊躇しないでください: これは 4 つの sse または 2 つの avx ベクトルにマップされ、必要な作業項目の数を 16 で割ります (これは CPU には適していますが、GPU には必ずしも適しているとは限りません: 私は 2 つの異なるCPU および GPU 用のカーネル)。

2) CPU のローカル メモリは RAM です。CPU カーネルでは使用しないでください。

3 と 4) よくわかりません。実装に依存しますが、フォークのオーバーヘッドは重要なようです。

于 2012-11-16T11:16:08.083 に答える