この質問に対する私の回答には、この問題についての長い説明があります。多くの人がこれらの質問を持っているという事実は、それが明らかではなく、アイデアに慣れるのに時間がかかることを証明しています。
知っておくべき重要なことは、MPI データ型が記述するメモリ レイアウトです。への呼び出しシーケンスMPI_Type_vector
は次のとおりです。
int MPI_Type_vector(int count,
int blocklength,
int stride,
MPI_Datatype old_type,
MPI_Datatype *newtype_p)
stride
すべてのアイテム、blocklength
引き出されたアイテムのブロック、およびcount
これらのブロックの合計があるメモリのレイアウトを記述する新しいタイプを作成します。ここのアイテムは、何の単位でもありold_type
ます。たとえば、(ここでパラメーターに名前を付けて、実際には C では実行できませんが、:)
MPI_Type_vector(count=3, blocklength=2, stride=5, old_type=MPI_INT, &newtype);
次にnewtype
、メモリ内のレイアウトを次のように記述します。
|<----->| block length
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| X | X | | | | X | X | | | | X | X | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|<---- stride ----->|
count = 3
ここで、各正方形は 1 つの整数サイズのメモリ チャンクであり、おそらく 4 バイトです。ストライドは、ブロック間の距離ではなく、1 つのブロックの開始から次のブロックの開始までの整数の距離であることに注意してください。
わかりましたので、あなたの場合は電話しました
MPI_Type_vector(N, 1, N, MPI_DOUBLE, &col);
count = N
これは、それぞれサイズ s のブロックを取り、sblocklength=1
MPI_DOUBLE
の各ブロックの先頭の間にスペースがありstride=N
MPI_DOUBLE
ます。つまり、N 番目の double ごとに、合計 N 回かかります。(連続して格納された) NxN 倍精度配列から 1 列を抽出するのに最適です。便利なチェックは、どのくらいのデータがまたがっているか (count*stride = N*N
行列のフル サイズ、チェック) と、実際に含まれているデータの量 ( count*blocksize = N
、列のサイズ、チェック) を確認することです。
MPI_Send と MPI_Recv を呼び出して個々の列を交換するだけでよい場合は、完了です。このタイプを使用して列のレイアウトを記述できれば問題ありません。しかし、もう1つあります。
を呼び出しMPI_Scatter
て、最初の coltype (たとえば) をプロセッサ 0 に送信し、次の coltype をプロセッサ 1 などに送信します。単純な 1d 配列でそれを行う場合、「次の」データ型がどこにあるかを簡単に把握できます。は; 各プロセッサに 1 つの int を分散している場合、最初の int が終了した直後に「次の」int が開始されます。
ただし、新しい coltype 列には、列の先頭からs までの合計範囲N*N
MPI_DOUBLE
があります。MPI_Scatter が同じロジックに従う場合 (そうです)、マトリックス メモリの外側にある「次の」列を完全に探し始めます。次と次のように。必要な答えが得られないだけでなく、プログラムがクラッシュする可能性があります。
これを修正する方法は、「次の」データ型がどこにあるかを計算するためのこのデータ型の「サイズ」が、1 つの列の開始位置と次の列の開始位置の間のメモリ内のサイズであることを MPI に伝えることです。つまり、ちょうど 1 つMPI_DOUBLE
です。これは、送信されるデータの量には影響しません。これは、依然として 1 列分のデータです。「次の行」の計算にのみ影響します。配列内の列 (または行) を使用して、このサイズをメモリ内の適切なステップ サイズに送信するだけで、MPI は送信する正しい次の列を選択します。このサイズ変更演算子がないと、プログラムがクラッシュする可能性があります。
上記にリンクされた 2D 配列の例の 2D ブロックのように、より複雑なデータ レイアウトがある場合、「次の」アイテム間に単一のステップ サイズはありません。サイズを有用な単位にするためにサイズ変更のトリックを行う必要がありますが、送信元の場所を明示的に指定するには、スキャッターではなくMPI_Scattervを使用する必要があります。