3

単一のマシンで複数のスレッドを使用して、浮動小数点値の配列の平均値を見つけようとしています。配列のサイズやメモリの制約は気にしません (適度なサイズの配列で、複数のスレッドを保証するのに十分な大きさであると仮定します)。特に、最も効率的なスケジューリング アルゴリズムを探しています。静的ブロックアプローチが最も効率的であるように思えます。

したがって、x 個のマシン コアがあることを考えると、配列を array.size/x 値にチャンクし、各コアにそれぞれの配列チャンクの結果を合計させるのが妥当と思われます。次に、各コアからの合計結果が加算され、最終結果は、この値を配列要素の総数で割ったものになります (注: 配列要素の数が x で正確に割り切れない場合、私は最適化を認識しています)要素をスレッド間でできるだけ均等に分散します)。

配列は明らかにスレッド間で共有されますが、書き込みが含まれていないため、ロック メカニズムを使用したり、同期の問題を心配したりする必要はありません。

私の質問は: これは実際にこの問題に対する最も効率的なアプローチですか?

対照的に、たとえば、静的インターリーブ アプローチを考えてみましょう。この場合、4 つのコア (スレッド) がある場合、スレッド 1 は配列要素 0、4、8、12... で動作し、スレッド 2 は要素 1、5、9、13... で動作します。各コアが継続的にキャッシュ ミスを取得するため、より悪いように見えますが、静的ブロック アプローチは、各コアが成功値に基づいて動作し、データの局所性を利用することを意味します。私が実行したいくつかのテストは、これを裏付けているようです。

では、静的ブロックよりも優れたアプローチを指摘したり、これが最善のアプローチである可能性が最も高いことを確認したりできる人はいますか?

編集:
Java と Linux (Ubuntu) を使用しています。関連する言語/プラットフォームについてはあまり考えずに、ワークロードを複数のスレッドに手動で割り当てることを含むスケジューリングの観点から問題を抽象的に見てください。しかし、言語とプラットフォームが重要な要素であることは理解しています。

Edit-2:
さまざまな配列サイズ (double) を使用したタイミング (ナノ時間/1000) を次に示します。
シーケンシャル タイミングでは、単一の Java スレッドが使用されました。他のものは、並行して動作するすべての利用可能な (4) コアを使用して、それぞれのスケジューリング戦略を実装しました。

1,000,000 要素 : ---
シーケンシャル
5765
1642
1565
1485
1444
1511 1511
1446
1448
1465
1443 ---
静的 ブロック
15857
4571
1489
1529
1547
1496
1445
1415
1452
1661
--- 静的 インター
レッド
9692







50,000,000 elements:
---Sequential
73757
69280
70255
78510
74520
69001
69593
69586
69399
69665
---Static Block
62827
52705
55393
53843
57408
56276
56083
57366
57081
57787
---Static Interleaved
179592
306106
239443
145630
171871
303050
233730
141827
162240
292421

4

1 に答える 1

3

お使いのシステムには、この問題で 4 つのスレッドを利用するためのメモリ帯域幅がないようです。要素の浮動小数点加算を行うだけでは、メモリがデータを配信できる速度で CPU をビジー状態に保つには十分な作業ではありません... 4 つのコアが同じメモリ コントローラ/DRAM を共有しており、メモリを待機しています。4 スレッドではなく 2 スレッドを使用すると、おそらく同じスピードアップが見られます。

あなたが言ったように、そしてあなたが確認したように、インターリーブは悪い考えです。貴重なメモリ帯域幅を浪費してデータをコアに持ち込み、その4分の1しか使用しないのはなぜですか。運が良く、スレッドがある程度同期して実行される場合は、レベル 2 またはレベル 3 キャッシュ内のデータを再利用できますが、それでもデータを L1 キャッシュに取り込み、一部しか使用しません。

更新: 5000 万の要素を追加する場合、懸念されるのは精度の低下です。5000 万の対数底 2 は約 26 ビットであり、倍精度浮動小数点には 53 の有効ビット (52 の明示的および 1 の暗黙的ビット) があります。最良のケースは、すべての要素の指数が類似している (大きさが類似している) 場合です。配列内の数値の指数の範囲が広い場合、事態はさらに悪化します。最悪の場合、範囲が大きく、大きさの降順で並べ替えられます。最終的な平均の精度は、配列を並べ替えて昇順に追加することで改善できます。多数の項目を追加する場合の精度の問題について詳しくは、この SO の質問を参照してください: Find the average within variable number of doubles .

于 2013-03-16T20:58:22.257 に答える