4 つの Intel プロセッサとそれぞれに 8 つのコアを搭載したマシンで並列コードを実行しています。TBB を使用しています。特定のループ (並列化する) に X 回の反復があるとします。負荷が均等に分割されるように、粒度を選択するにはどうすればよいですか?
2 に答える
同等に強力な N 個の CPU があるとします。
ループ実行依存関係がない場合 (たとえば、反復 i で後続の反復によって使用されるものがない場合)、CPU 1 でループ反復 0..X/N を実行し、反復 (X/N)+1..( CPU 2 で 2*X/N) など、各反復にかかる時間がまったく同じか、少なくともその平均時間が大きく変動しないと仮定します。
ループ運搬の依存関係がある場合、反復 i が以前のすべての反復に依存している場合、問題が発生する可能性があります。前の k 回の反復のみに依存する場合、CPU1 に反復 0..X/N を実行させ、CPU2 に反復 X/Nk..(2*X/N) を実行させることができます。すべてのプロセッサに必要な結果など。
反復にかかる時間が大幅に異なる場合は、反復を含むワークリストを設定し、CPU が前の反復を完了するときにワークリストから反復を取得することをお勧めします。このようにして、需要が発生すると作業が分割されます。取得される作業単位あたりの時間が、作業を取得するための労力よりもはるかに大きいことを確認する必要があります。そうしないと、同等の利点が得られません。これを行う 1 つの方法は、範囲内の合計作業がスケジューリングのオーバーヘッドを大幅に超えるように、ワークリストから小さな範囲の反復を取得することです。
TBB では、parallel_for の粒度を選択する必要はありません。ほとんどの場合、TBB はデフォルトで作業を動的に負荷分散します。Ira Baxter の回答は、スレッドのプール全体で作業を分割する方法を正しく説明しています。しかし、TBB には、これを行う同様のメカニズムが既に用意されています。
追加: 複雑なケースでは、手動作業のパーティショニングがより良い結果をもたらす可能性があります。ただし、この場合、parallel_for では十分な制御が提供されない可能性があるため、TBB タスクを使用する必要がある可能性があります。たとえば、一般に、スレッドごとのチャンクの正確なサイズを指定することはできません。