MPI_Reduce无法按预期工作

时间:2012-12-02 03:01:53

标签: c mpi openmpi reduction

我是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很新,我可能会犯一个明显的错误。我在网上看到的所有教程都有类似于我的代码示例,我不知道我做错了什么。

谢谢,

可以。

1 个答案:

答案 0 :(得分:3)

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是排名0中arr的副本,arr_1是排名1中arr的副本,依此类推。

MPI_Bcast的组合,然后是MPI_MAX的缩减 abosly nothing nothing ,因为arr的所有副本在广播后都具有相同的值元素明确max减少的应用只会产生相同的值。更糟糕的是,我认为你的代码中的result是一个标量整数变量,因此MPI_Reduce会覆盖arraysize-1以后的result元素并且很可能会破坏堆栈帧,覆盖等级my_process_id0的值,因此不再是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);