如何将MPI_Reduce转换为MPI_Send和MPI_Recv?
我正在开发一个使用MPI_Send()和MPI_Recv()而不是使用MPI_Reduce()的并行处理程序。我知道MPI_Send()需要从每个处理器向根处理器(也称为0)发送一个值,MPI_Recv()需要从每个处理器接收所有值 我不断得到一个错误,其中Send中的值不会发送到接收方,因此最终值为0。MPI_Reduce()函数仍在代码中,但已注释掉,以查看需要替换的内容。有人能帮忙吗如何将MPI_Reduce转换为MPI_Send和MPI_Recv?,c,parallel-processing,mpi,C,Parallel Processing,Mpi,我正在开发一个使用MPI_Send()和MPI_Recv()而不是使用MPI_Reduce()的并行处理程序。我知道MPI_Send()需要从每个处理器向根处理器(也称为0)发送一个值,MPI_Recv()需要从每个处理器接收所有值 我不断得到一个错误,其中Send中的值不会发送到接收方,因此最终值为0。MPI_Reduce()函数仍在代码中,但已注释掉,以查看需要替换的内容。有人能帮忙吗 #include "mpi.h" #include <stdio.h> #
#include "mpi.h"
#include <stdio.h>
#include <math.h>
int main( int argc, char *argv[])
{
int n, i;
double PI25DT = 3.141592653589793238462643;
double pi, h, sum, x;
int numprocs, myid;
double startTime, endTime;
/* Initialize MPI and get number of processes and my number or rank*/
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
/* Processor zero sets the number of intervals and starts its clock*/
if (myid==0) {
n=600000000;
startTime=MPI_Wtime();
for (int i = 0; i < numprocs; i++) {
if (i != myid) {
MPI_Send(&n, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
}
}
}
else {
MPI_Recv(&n, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
/* Calculate the width of intervals */
h = 1.0 / (double) n;
/* Initialize sum */
sum = 0.0;
/* Step over each inteval I own */
for (i = myid+1; i <= n; i += numprocs) {
/* Calculate midpoint of interval */
x = h * ((double)i - 0.5);
/* Add rectangle's area = height*width = f(x)*h */
sum += (4.0/(1.0+x*x))*h;
}
/* Get sum total on processor zero */
//MPI_Reduce(&sum,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
double value = 0;
if (myid != 0) {
MPI_Send(&sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
else {
for (int i = 1; i < numprocs; i++) {
MPI_Recv(&value, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
pi += value;
}
}
/* Print approximate value of pi and runtime*/
if (myid==0) {
printf("pi is approximately %.16f, Error is %e\n",
pi, fabs(pi - PI25DT));
endTime=MPI_Wtime();
printf("runtime is=%.16f",endTime-startTime);
}
MPI_Finalize();
return 0;
}
#包括“mpi.h”
#包括
#包括
int main(int argc,char*argv[])
{
int n,i;
双PI25DT=3.141592653589793238462643;
双π,h,和,x;
int numprocs,myid;
双开始时间,结束时间;
/*初始化MPI并获取进程数和我的编号或排名*/
MPI_Init(&argc,&argv);
MPI通信大小(MPI通信世界和numprocs);
MPI通信等级(MPI通信世界和myid);
/*处理器zero设置间隔数并启动其时钟*/
如果(myid==0){
n=600000000;
startTime=MPI_Wtime();
for(int i=0;i 对于(i=myid+1;i您正在使用MPI\u INT
发送类型为double
的值:
if(myid!=0){
MPI_发送(&sum,1,MPI_INT,0,0,MPI_COMM_WORLD);
// ^^^^^^^
}
int
的长度为4字节;double
的长度为8字节。虽然接收操作成功,但如果消息中只有4个字节,它无法构造类型为MPI\u double
的值,因此它不会将任何内容写入value
中,并且仍然保持0.0
。如果替换:
MPI\u Recv(&value,1,MPI\u DOUBLE,i,0,MPI\u COMM\u WORLD,MPI\u STATUS\u IGNORE);
与
MPI\u状态;
整数计数;
MPI_Recv(&value,1,MPI_DOUBLE,i,0,MPI_COMM_WORLD,&status);
MPI\u获取计数(&status,MPI\u DOUBLE,&count);
如果(计数==未定义的MPI_){
printf(“收到短消息”);
MPI_中止(MPI_通信世界,0);
}
您的程序将中止,这表明由于MPI\u Get\u count()
在count
中返回MPI\u UNDEFINED
,执行了条件语句体,这表明接收到的消息长度不是MPI\u DOUBLE
大小的整数倍
此外,在接收循环之前,pi
必须显式初始化为sum
,否则由于以下任一错误,您将获得错误的pi
值:
pi
未初始化且具有任意初始值,以及
- 等级0的贡献不会添加到最终结果中