5

最近、16コアプロセッサで並列計算が実際にどのように高速化されるかを分析しています。そして、私が結論付けた一般式(スレッドが多いほど、コアあたりの速度が遅くなります)は、私を当惑させます。これが私のCPU負荷と処理速度の図です:

写真1

したがって、プロセッサの負荷は増加しますが、速度の増加ははるかに遅くなります。なぜそのような効果が発生するのか、そしてスケーラブルでない振る舞いの理由をどのように取得するのかを知りたいです。サーバーGCモードを使用するようにしました。コードが何もしないとすぐに、適切なコードを並列化することを確認しました

  • RAMからデータをロードします(サーバーには96 GBのRAMがあり、スワップファイルはヒットしないでください)
  • 複雑ではない計算を実行します
  • データをRAMに保存します

アプリケーションのプロファイルを注意深く調べたところ、ボトルネックは見つかりませんでした。スレッド数が増えると、各操作が遅くなるようです。

私は立ち往生しています、私のシナリオの何が問題になっていますか?

.Net4タスク並列ライブラリを使用しています。

4

5 に答える 5

10

あなたはいつもこの種の曲線を得るでしょう、それはアムダールの法則と呼ばれています。
問題は、それがどれだけ早く横ばいになるかということです。

コードのボトルネックをチェックしたとのことですが、それが正しいと仮定しましょう。それでも、メモリ帯域幅とその他のハードウェア要因があります。

于 2012-10-11T18:31:37.860 に答える
5

線形スケーラビリティの鍵は、1コアから2コアに移行するとスループットが2倍になるという状況で、共有リソースの使用をできるだけ少なくすることです。これの意味は:

  • ハイパースレッディングを使用しないでください(2つのスレッドが同じコアリソースを共有するため)
  • すべてのスレッドを特定のコアに結び付けます(そうでない場合、OSはコア間でスレッドをジャグリングします)
  • コアよりも多くのスレッドを使用しないでください(OSはスワップインおよびスワップアウトします)
  • コア自体のキャッシュ内にとどまる-現在、L1およびL2キャッシュ
  • どうしても必要な場合を除いて、L3キャッシュやRAMに足を踏み入れないでください
  • クリティカルセクション/同期の使用を最小化/経済化

ここまで来たら、おそらくコードのプロファイルを作成して手動で調整したことでしょう。

スレッドプールは妥協案であり、妥協のない高性能アプリケーションには適していません。トータルスレッドコントロールはです。

OSスケジューラについて心配する必要はありません。アプリケーションがCPUにバインドされており、ほとんどの場合ローカルL1およびL2メモリアクセスを行う長い計算を行う場合は、各スレッドを独自のコアに結び付ける方がパフォーマンスが向上します。確かにOSは入りますが、スレッドによって実行されている作業と比較すると、OSの作業はごくわずかです。

また、私のスレッド体験は主にWindowsNTエンジンマシンからのものであると言わなければなりません。

__ _ ____編集____ __ _ _ _ _ _

すべてのメモリアクセスがデータの読み取りと書き込みに関係しているわけではありません(上記のコメントを参照)。見過ごされがちなメモリアクセスは、実行するコードをフェッチすることです。したがって、コア自体のキャッシュ内にとどまるという私の声明は、必要なすべてのデータとコードがこれらのキャッシュに存在することを確認することを意味します。非常に単純なOOコードでさえ、ライブラリルーチンへの非表示の呼び出しを生成する可能性があることも覚えておいてください。この点(コード生成部門)では、OOおよびインタープリターされたコードはおそらくC(通常はWYSIWYG)またはもちろんアセンブリー(完全にWYSIWYG)よりもはるかに少ないWYSIWYGです。

于 2012-10-11T22:05:01.817 に答える
3

より多くのスレッドでの見返りの一般的な減少は、ある種のボトルネックを示している可能性があります。

コレクションやキューなどの共有リソースはありますか、または限られたリソースに依存している可能性のある外部機能を使用していますか?

8スレッドでの急激な中断は興味深いものであり、私のコメントでは、CPUが真の16コアであるか、ハイパースレッディングを備えた8コアであるかを尋ねました。ここで、各コアはOSに対して2コアとして表示されます。

ハイパースレッディングの場合は、ハイパースレッディングでコアのパフォーマンスを2倍にできないほど多くの作業が発生するか、コアへのメモリパイプでデータスループットを2倍に処理できません。

スレッドによって実行される作業は同じですか、それとも一部のスレッドが他のスレッドよりも多くのことを実行していますか。これは、リソースの不足を示している可能性もあります。

そのスレッドがデータを頻繁に照会することを追加したので、それは待機の非常に大きなリスクを示しています。

スレッドが毎回より多くのデータを取得できるようにする方法はありますか?1つではなく10のアイテムを読むのが好きですか?

于 2012-10-11T18:29:57.347 に答える
1

メモリを大量に消費する処理を行っている場合は、キャッシュ容量に達している可能性があります。

データが何度も繰り返される場合は同じ小さなビットを処理するだけのモックアルゴリズムでこれをテストして、すべてがキャッシュに収まるようにすることができます。

それが実際にキャッシュである場合、考えられる解決策は、スレッドを同じデータで何らかの形で機能させる(小さなデータウィンドウのさまざまな部分など)か、アルゴリズムをよりローカルに調整する(並べ替えのように、マージソートは一般にクイックソートよりも遅い)可能性があります、しかし、それはよりキャッシュフレンドリーであり、それでも場合によってはそれをより良くします)。

于 2012-10-11T18:33:51.527 に答える
1

あなたのスレッドは、メモリ内でアイテムの読み取りと書き込みを密接に行っていますか?次に、おそらく偽共有に遭遇しています。スレッド1がdata[1]で動作し、thread2がdata [2]で動作する場合、理想的な世界では、thread2によるdata [2]の2つの連続した読み取りは、実際の世界では常に同じ結果を生成することがわかっています。 thread1がこれら2つの読み取りの間にdata[1]を更新すると、CPUはキャッシュをダーティとしてマークして更新します。http://msdn.microsoft.com/en-us/magazine/cc872851.aspx。これを解決するには、各スレッドが処理しているデータが、他のスレッドが処理しているデータからメモリ内で十分に離れていることを確認します。

これによりパフォーマンスが向上する可能性がありますが、16倍にはならない可能性があります。内部では多くのことが行われているため、1つずつノックアウトする必要があります。そして実際には、マルチスレッド化されたときにアルゴリズムが30%の速度で実行されているわけではありません。さらに、シングルスレッドアルゴリズムは300%の速度で実行されており、あらゆる種類のCPUとキャッシュの素晴らしさによって実現されており、マルチスレッドの実行では利用するのが困難です。したがって、「困惑」することは何もありません。 しかし、ある程度の注意を払えば、マルチスレッドバージョンをほぼ300%の速度で動作させることができるかもしれません。

また、ハイパースレッドコアを実際のコアとして数えている場合は、そうではありません。それらは、1つがブロックされている場合にのみ、スレッドが非常に高速にスワップできるようにします。ただし、スレッドが半分の時間ブロックされていない限り、2倍の速度で実行することはできません。その場合、すでにスピードアップの機会があります。

于 2012-10-12T16:24:08.023 に答える