エグゼクティブサマリー:OpenMPがREALコアのスレッドのみを使用する、つまりハイパースレッディングコアをカウントしないようにコードで指定するにはどうすればよいですか?
詳細な分析:何年にもわたって、私は空き時間にSWのみのオープンソースレンダラー(ラスタライザー/レイトレーサー)をコーディングしてきました。GPLコードとWindowsバイナリは、次の場所から入手できます 。https ://www.thanassis.space/renderer.html Windows、Linux、OS / X、およびBSDでコンパイルおよび実行されます。
私は先月レイトレーシングモードを導入しました-そして生成された写真の品質は急上昇しました。残念ながら、レイトレーシングはラスター化よりも桁違いに遅くなります。速度を上げるために、ラスターライザーの場合と同じように、レイトレーサーにOpenMP(およびTBB)のサポートを追加して、追加のCPUコアを簡単に利用できるようにしました。ラスター化とレイトレーシングはどちらも、スレッド化に簡単に対応できます(三角形ごとの作業-ピクセルごとの作業)。
自宅では、私のCore2Duoを使用して、2番目のコアがすべてのモードを支援しました。ラスター化モードとレイトレーシングモードの両方で、1.85倍から1.9倍のスピードアップが得られました。
問題:当然、最高のCPUパフォーマンス(GPU、予備のCUDAポートでも「遊ぶ」)を知りたいと思ったので、比較のための強固な基盤が必要でした。私は、16コア、1500ドルのIntelスーパープロセッサを搭載した「ビースト」マシンにアクセスできる私の親友にコードを渡しました。
彼はそれを「最も重い」モードであるレイトレーサーモードで実行します。
...そして彼は私のCore2Duoの5分の1の速度を手に入れました(!)
ガスプ-ホラー。今何があったの?
私たちはさまざまな修正やパッチを試し始めました...そして最終的にそれを理解しました。
OMP_NUM_THREADS環境変数を使用することにより、生成されるOpenMPスレッドの数を制御できます。スレッドの数が1から8に増加するにつれて、速度は増加していました(直線的な増加に近い)。8を超えた瞬間、速度が低下し始め、16コアすべてが使用されたときに、Core2Duoの速度の5分の1に急降下しました。
なぜ8?
8が実際のコアの数だったからです。他の8つは...ハイパースレッディングのものでした!
理論:さて、これは私にとってニュースでした-ハイパースレッディングが他のアルゴリズムで大いに役立つ(最大25%)のを見たので、これは予想外でした。どうやら、各ハイパースレッディングコアには独自のレジスタ(およびSSEユニット?)が付属していますが、レイトレーサーは追加の処理能力を利用できませんでした。それは私に考えさせました...
不足しているのはおそらく処理能力ではなく、メモリ帯域幅です。
レイトレーサーは、バウンディングボリューム階層データ構造を使用して、レイトライアングルの交差を加速します。ハイパースレッドコアが使用されている場合、ペアの各「論理コア」は、そのデータ構造内のさまざまな場所(つまりメモリ内)から読み取ろうとします。CPUキャッシュ(ペアごとにローカル)は完全に破棄されます。少なくとも、それは私の理論です-どんな提案も大歓迎です。
したがって、質問: OpenMPは「コア」の数を検出し、それに一致するスレッドを生成します。つまり、計算にハイパースレッドの「コア」が含まれます。私の場合、これは明らかに悲惨な結果につながります。OpenMP APIを使用して(可能であれば移植可能に)REALコアのスレッドのみを生成し、ハイパースレッドのスレッドは生成しない方法を知っている人はいますか?
PSコードはオープン(GPL)であり、上記のリンクから入手できます。ご使用のマシンで自由に再現してください。これは、すべてのハイパースレッドCPUで発生すると思います。
PPS投稿の長さすみません、それは教育的な経験だと思い、共有したいと思いました。