MPI_Reduce
想定どおりに機能します。あなたはそれが使われることになっている方法でそれを使わない人です。
MPI_Reduce
MPIジョブのランク間で分散されたデータの要素ごとの削減を実行します。ソースバッファとデスティネーションバッファの両方がサイズの配列である必要がありますarraysize
。例:
int arr[arraysize];
int result[arraysize];
// Fill local arr with meaningful data
...
// Perform reduction
MPI_Reduce(arr, result, arraysize, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce
次は何ですか。
result[0] = max(arr_0[0], arr_1[0], ..., arr_(N-1)[0]);
result[1] = max(arr_0[1], arr_1[1], ..., arr_(N-1)[1]);
...
result[arraysize-1] = max(arr_0[arraysize-1], ..., arr_(N-1)[arraysize-1]);
ここarr_0
で、arr
はランク0arr_1
のコピー、arr
はランク1のコピー、というように続きます。
の組み合わせとMPI_Bcast
それに続くとの削減は、ブロードキャスト後にすべてのコピーが同じ値を持ち、要素ごとの削減を適用すると単純に同じ値が得られるため、まったく何もMPI_MAX
しません。さらに悪いことに、あなたのコードにはスカラー整数変数があると思います。したがって、過去の要素を上書きし、スタックフレームを破壊し、ランクの値を上書きして、それ以上(したがって何も出力されない)、ランクをクラッシュさせる可能性があります。その後。もちろん、それはすべて、ローカル変数がスタック内でどのように配置されているかに依存します。その影響は、私が説明したほど深刻ではない可能性があります。arr
max
result
MPI_Reduce
arraysize-1
result
my_process_id
0
0
0
配列の最大値を見つけたい場合は、最初にを使用して配列を分散しMPI_Scatter
、次にを使用MPI_Reduce
して要素ごとの削減を実行してから、結果に対して別の削減を実行する必要があります。
int elements_per_proc = arraysize/number_of_processes;
int arr[arraysize];
int subarr[elements_per_proc];
int partres[elements_per_proc];
// Distribute the array
MPI_Scatter(arr, elements_per_proc, MPI_INT,
subarr, elements_per_proc, MPI_INT, 0, MPI_COMM_WORLD);
// Perform element-wise max reduction
MPI_Reduce(subarr, partres, elements_per_proc, MPI_INT,
MPI_MAX, 0, MPI_COMM_WORLD);
// Take the highest of the partial max values
result = partres[0];
for (int i = 1; i < elements_per_proc; i++)
if (partres[i] > result) result = partres[i];
これで、の最大要素の値が得られましたresult
。
またはさらに良い:
int localmax;
// Distribute the array
MPI_Scatter(arr, elements_per_proc, MPI_INT,
subarr, elements_per_proc, MPI_INT, 0, MPI_COMM_WORLD);
// Find the maximum element of the local subarray
localmax = subarr[0];
for (int i = 1; i < elements_per_proc; i++)
if (subarr[i] > localmax) localmax = subarr[i];
// Perform global max reduction
MPI_Reduce(&localmax, &result, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);