私はローカルワークサイズによって、同時に並列に使用される のスレッド数が決まると思いましたが、本当に正しいですか?
正解ですが、コンピューティングユニットごとであり、デバイス全体ではありません。ローカルスレッドグループよりも計算単位が多い場合、デバイスは完全には使用されません。正確な倍数ではなく、計算ユニットより多くのスレッドグループがある場合、計算ユニットの中には、最後に他の計算ユニットを待つものがあります。両方の値が等しい(または正確に複数の)場合、「何回」がすべてのALUSを完全に占有することが重要です。
たとえば、8コアのCPUは8つの計算単位を定義できます(ハードウェアマルチスレッドの場合は+ 8以上)。しかし、同様の価格を持つGPUには、20から64までのコンピューティングユニットがあります。単一のコンピューティングユニット内であっても、スレッドの多くのグループは明示的にチューニングされず、スレッドごとおよび計算単位ごと、そしておそらくGPUごとにリソース使用量によって変更される「飛行中」になる可能性があります。
どのようにローカルサイズの変更がそのコードに影響しますか?私は明らかに グローバルIDで作業しているので、ローカルのサイズは より大きいものにローカルな変更はありませんより1つは、その アルゴリズムの実行に費やした時間に影響を与えると言いますか?
ベクトル化可能/並列化可能なカーネルコードは、ALU、gpu計算ユニットのコアまたはより広いSIMDのSIMDにスレッドを配布する利点があります。 CPUの場合、同時に8つのスカラ命令を発行することができます。 GPUの場合、それは何千もの大きさになる可能性があります。したがって、ローカルサイズを1に減らすと、並列スレッドのスレッド幅が1 ALUに制限され、多くのアーキテクチャでパフォーマンスが低下します。ローカルサイズを大きくしすぎると、スレッドごとのリソースが低下し、パフォーマンスが低下します。もしあなたが何も考えていなければ、opencl apiはそのパラメータにヌルを与えればあなたのローカルサイズを調整することができます。
そして、そのアルゴリズムでループを使用するときは、ローカルサイズの影響については を変更していますか?ローカルサイズを変更するときに相違点を確認するには、 local_idを使用する必要がありますか?
古いスケジューリングアーキテクチャと静的スケジューリングアーキテクチャでは、ループアンローリングには、基本SIMD幅の幅に等しいアンロールステップサイズが必要です。いいえ、ローカルIDは計算ユニット内のスレッドIDの単なるクエリなので、必要ない場合はクエリする必要はありません。
は、私は私のプログラムのいくつかにそれをテストし、私は地元の仕事の大きさを変えるだけ global_id年代を使用した場合であっても、私に大幅に短縮 実行する時間を与えました。それでどうやって動くの?
カーネルに無駄なリソースが必要な場合は、ローカルグループごとに1つのスレッドを考えることができます。カーネルが即値以外のリソースを必要としない場合は、ローカル値を最大にする必要があります。スレッドごとのリソース割り当て(カーネルコードのため)が重要です。新しいアーキテクチャにはロードバランシングがあるので、将来的にAPIが最適な値を選択するかどうかは重要ではありません。
スケジューラは、すべてのALUをビジー状態に保つために、コアごとに多くのスレッドを発行します。スレッドがメモリ操作を待っているときに、別のスレッドがALU操作を同時に行うことができます。これは、リソースの使用量が少ない場合に適しています。計算ユニットのすべてのリソースの%50を使用すると、飛行中のスレッドは2つしかない可能性があります。スレッドは、L1キャッシュ、ローカルメモリ、レジスタファイルなどの共有可能なリソースを共有します。
スカラー浮動小数点のためのc [i] = a [i] + b [i]などのコードはベクトル化可能です。コンパイラがバックグラウンドでそれをやっていない場合は、float8、float16などの構造体を使ってパフォーマンスを向上させることができます。これにより、すべての作業を達成するために必要なスレッドが少なくて済み、メモリへのアクセスも高速になります。また、カーネルにループを追加してスレッド数をさらに減らすこともできます。これは、2つのデータブロックの間にスレッドディスパッチが少なくて済むため、CPUに適しています。 GPUでは問題ではないかもしれません。
トリビアル例えばCPU用:
4コア、ローカルサイズ= 10、グローバルサイズ= 100
コア1及び2は、3つのスレッドグループそれぞれを有しています。コア3とコア4にはスレッドグループが2つしかありません。
- 1:30スレッド - >完全パフォーマンス
- 2:30スレッド
- 3:20スレッド - >以下パフォーマンス、他のジョブのためのより良いプリエンプション
- 4:20スレッド
命令パイプライニングではコア1とコア2のバブルはあまりありませんが、コア3とコア4ではしばらくしてからバブルが開始されるため、並列またはオペレーティングシステムまたは一部のアレイで実行されている2番目のカーネルコピー。 120スレッドのようにすべてのコアを等しく使用すると、1秒あたりの処理量は増えますが、すでにカーネルがメモリを使用している場合、CPUは配列コピーを実行できません。(OSが他のスレッドに優先しない限り)