2

私はMPIを初めて使用し、MPI_Reduceを使用して整数配列の最大値を見つけようとしています。arrサイズの整数配列がarraysizeあり、コードは次のとおりです。

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &number_of_processes);
MPI_Comm_rank(MPI_COMM_WORLD, &my_process_id);
MPI_Bcast(arr, arraysize, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Reduce(arr, &result, arraysize, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);

if(!my_process_id){
    printf("%d", result);
}

MPI_Finalize();

私のプログラムは8つのプロセスで問題なくコンパイルおよび実行されますが、画面には何も出力されません。デバッグの目的で、条件をif(my_process_id)(なしで!)に変更して実行します。00030000次に、3がこのリストのどこかに非決定的に存在する可能性があるなどの奇妙な出力が得られます。3は私の配列の最初の値です(ただし最大値ではありません)。私は一般的に並列プログラミングについて知っていますが(専門家ではありませんが、通常は自分が何をしているのかを知っています)、MPIは非常に新しいので、明らかな間違いをしている可能性があります。私がオンラインで見たすべてのチュートリアルには、私のようなコードサンプルがあり、何が間違っているのかわかりません。

ありがとう、

できる。

4

1 に答える 1

3

MPI_Reduce想定どおりに機能します。あなたはそれが使われることになっている方法でそれを使わない人です。

MPI_ReduceMPIジョブのランク間で分散されたデータの要素ごとの削減を実行します。ソースバッファとデスティネーションバッファの両方がサイズの配列である必要があります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しません。さらに悪いことに、あなたのコードにはスカラー整数変数があると思います。したがって、過去の要素を上書きし、スタックフレームを破壊し、ランクの値を上書きして、それ以上(したがって何も出力されない)、ランクをクラッシュさせる可能性があります。その後。もちろん、それはすべて、ローカル変数がスタック内でどのように配置されているかに依存します。その影響は、私が説明したほど深刻ではない可能性があります。arrmaxresultMPI_Reducearraysize-1resultmy_process_id000

配列の最大値を見つけたい場合は、最初にを使用して配列を分散し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);
于 2012-12-02T13:09:00.097 に答える