2011-09-15 10 views
1

MPIで実行されるすべてのプロセッサで同一の配列のすべての値に対する更新を含むコードの効率を改善したいと思います。私が今使っている基本的な構造は、各プロセッサのローカル配列にデータのmemcpyチャンクを入れ、それらを操作し、Allgatherv(ローカルブロックのサイズが厳密に同じではないため「v」を使用する必要があります)です。結局のところ、これは非常に効率的ではありません、すべてのタスクで同一の配列をMPIで効率的に更新

/* counts gives the parallelization, counts[RANK] is the local memory size */ 
/* offsets gives the index in the global array to the local processors */ 

memcpy (&local_memory[0], &total_vector[0], counts[RANK] * sizeof (double)); 
for (i = 0; i < counts[RANK]; i++) 
    local_memory[i] = new_value; 

MPI_Allgatherv (&local_memory[0], counts[RANK], MPI_DOUBLE, &total_vector[0], counts, offsets, MPI_DOUBLE, MPI_COMM_WORLD); 

Cでは、これは次のようになります。実際、それは実際には遅いので、並列化に興味があるほとんどのシステム・サイズで速度が向上するわけではありません。

これは、各プロセッサのグローバルベクトルのローカルチャンクだけを更新し、正しいタスクから正しいすべてのタスクを他のすべてのタスクにブロードキャストすることです。これにより、明示的なメモリ処理が回避されますが、ブロードキャストの通信コストはかなり高くなければなりません。効果的にはすべてがすべてです。

編集:このソリューションを試してみました。ここでは、タスク数をループしてその数のブロードキャスト文を実行する必要がありました。この方法はさらに悪いことです。

誰かがより良い解決策を持っていますか?

+0

これを正しく理解していることを確認するには:各プロセッサはベクトルの特定の部分を更新する必要があります。そして、すべてのプロセッサは、最終的に他のすべてのプロセッサからアップデートを取得する必要がありますか? (彼らは同じであると思われるので) – Mysticial

+0

あなたはそれを持っている。 – coastal

+0

私はそれがより良くなるか悪化するかについて答えを投稿しようとしており、あなたは自分自身で答えました。私はアイデアがありません。カスタムのMPIデータ型でハックする可能性はありますが、あまりにも慣れていません。 – Mysticial

答えて

0

あなたが記述するアルゴリズムは「すべてに」です。各ランクはより大きなアレイの一部を更新し、すべてのランクはそのアレイを時々同期させる必要があります。

プログラムフローの制御されたポイントで更新が行われる場合は、ギャザー/散布パターンが効果的です。すべてのランクは「ランク0」に更新を送信し、ランク0は更新されたアレイを他のすべてに送信します。アレイのサイズ、ランクの数、各ランク間の相互接続などに依存して、このパターンはAllgathervよりも少ないオーバーヘッドを提供することができる。

関連する問題