MPI_Reduce 完全按照它应该的方式工作。没有按照应有的方式使用它。
MPI_Reduce 执行element-wise 数据缩减,分布在 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 是排名0 中arr 的副本,arr_1 是排名1 中arr 的副本,依此类推。
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);