如果我有这段代码:
int main(void) {
int result=0;
int num[6] = {1, 2, 4, 3, 7, 1};
if (my_rank != 0) {
MPI_Reduce(num, &result, 6, MPI_INT, MPI_MIN, 0, MPI_COMM_WORLD);
} else {
MPI_Reduce(num, &result, 6, MPI_INT, MPI_MIN, 0, MPI_COMM_WORLD)
printf("result = %d\n", result);
}
}
结果打印为1;
但如果是num[0]=9
;然后结果是9
我阅读解决这个问题我必须将变量num
定义为数组。
我无法理解函数MPI_Reduce
如何与MPI_MIN
一起使用。为什么,如果num[0]
不等于最小数字,那么我必须将变量num
定义为数组?
答案 0 :(得分:3)
MPI_Reduce
执行通信器成员的减少 - 而不是本地数组的成员。 sendbuf
和recvbuf
必须都是size
。{/ p>
我认为the standard说得最好:
因此,所有进程都提供输入缓冲区和相同长度的输出缓冲区,具有相同类型的元素。每个进程可以提供一个元素,或一系列元素,在这种情况下,组合操作在序列的每个条目上按元素执行。
MPI没有得到阵列中所有元素的最小值,你必须手动完成。
答案 1 :(得分:1)
您可以使用MPI_MIN获取通过缩减传递的最小值。 让我们检查函数声明:
int MPI_Reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype
datatype, MPI_Op op, int root, MPI_Comm comm)
每个进程使用缓冲区sendbuff
发送它的值(或值数组)。
由root
id标识的进程接收缓冲区并将它们存储在缓冲区recvbuf
中。从计数中指定从每个其他进程接收的元素数,因此必须使用维recvbuff
分配sizeof(datatype)*count
。
如果每个进程只有一个要发送的整数(count = 1),那么recvbuff
它也是一个整数,如果每个进程有两个整数,那么recvbuff
它是一个大小为2的整数数组。看到这个很好{ {3}}进一步解释和漂亮的图片。
现在应该清楚您的代码是错误的,sendbuff
和recvbuff
必须具有相同的大小,并且不需要条件:if(myrank==0)
。简单来说,recvbuff
仅对root
进程有意义,对其他进程有sendbuff
。
在您的示例中,您可以将数组的一个或多个元素分配给不同的进程,然后计算minvalue(如果有与数组中的值一样多的进程)或minvalues数组(如果有多个值而不是进程)。
这是一个工作示例,说明了在简单值(不是数组)的情况下MPI_MIN,MPI_MAX和MPI_SUM(稍微修改自post)的用法。 每个进程根据其等级执行一些工作,并将完成工作所花费的时间发送给根进程。根进程收集时间并输出时间的最小值,最大值和平均值。
#include <stdio.h>
#include <mpi.h>
int myrank, numprocs;
/* just a function to waste some time */
float work()
{
float x, y;
if (myrank%2) {
for (int i = 0; i < 100000000; ++i) {
x = i/0.001;
y += x;
}
} else {
for (int i = 0; i < 100000; ++i) {
x = i/0.001;
y += x;
}
}
return y;
}
int main(int argc, char **argv)
{
int node;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &node);
printf("Hello World from Node %d\n",node);
/*variables used for gathering timing statistics*/
double mytime,
maxtime,
mintime,
avgtime;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Barrier(MPI_COMM_WORLD); /*synchronize all processes*/
mytime = MPI_Wtime(); /*get time just before work section */
work();
mytime = MPI_Wtime() - mytime; /*get time just after work section*/
/*compute max, min, and average timing statistics*/
MPI_Reduce(&mytime, &maxtime, 1, MPI_DOUBLE,MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce(&mytime, &mintime, 1, MPI_DOUBLE, MPI_MIN, 0,MPI_COMM_WORLD);
MPI_Reduce(&mytime, &avgtime, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);
/* plot the output */
if (myrank == 0) {
avgtime /= numprocs;
printf("Min: %lf Max: %lf Avg: %lf\n", mintime, maxtime,avgtime);
}
MPI_Finalize();
return 0;
}
如果我在我的OSX笔记本电脑上运行它,这就是我得到的:
urcaurca$ mpirun -n 4 ./a.out
Hello World from Node 3
Hello World from Node 0
Hello World from Node 2
Hello World from Node 1
Min: 0.000974 Max: 0.985291 Avg: 0.493081