C MPI pi计算中的节点计数无效

C MPI pi计算中的节点计数无效,c,parallel-processing,openmp,openmpi,C,Parallel Processing,Openmp,Openmpi,我正在尝试将以下代码并行化以计算pi 我的方法是使用散布来并行化for,然后使用reduce来计算和值,最后显示pi 我的代码如下 #include <stdio.h> #include <mpi.h> long num_steps = 100000; double step = 1.0/100000.0; int main() { int i, myid, size; double x, pi, local_sum = 0.0, sum=0.0; double

我正在尝试将以下代码并行化以计算pi

我的方法是使用散布来并行化for,然后使用reduce来计算和值,最后显示pi

我的代码如下

#include <stdio.h>
#include <mpi.h> 

long num_steps = 100000;
double step = 1.0/100000.0;

int main() {

int i, myid, size;
double x, pi, local_sum = 0.0, sum=0.0;
double send_vec[num_steps], recv_vect[num_steps]; 

// Initialize the MPI environment 
MPI_Init(NULL, NULL); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 
MPI_Comm_rank(MPI_COMM_WORLD,&myid);

if (myid ==0){
    int i=0; 
    for (i=0; i<num_steps;i++){
        send_vec[i]=i;
    }
}

MPI_Scatter(send_vec, num_steps/size, MPI_INT, recv_vect, 
    num_steps, MPI_INT, 0, MPI_COMM_WORLD);

for(i = 0; i < num_steps; ++i) {
    x = (recv_vect[i]-0.5)*step;
    local_sum += 4.0/(1.0+x*x);
}

MPI_Reduce(&local_sum, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

if (myid == 0){
    pi = step*sum;
    printf("PI value = %f\n", pi);  
 }

// Finalize the MPI environment. 
MPI_Finalize();
}

要更正对
MPI\u Scatter()
的调用:

MPI_Scatter(send_vec, num_steps/size, MPI_INT, recv_vect, 
num_steps, MPI_INT, 0, MPI_COMM_WORLD);
  • 要发送
    double
    ,请像在
    MPI\u Reduce()中那样使用数据类型
    MPI\u double
  • 由于
    sendtype
    recvtype
    类似,发送到每个进程
    sendcount
    的项目数必须等于每个进程
    recvcount
    接收的项目数。在本例中,它是
    num\u步数/size
最后,对
MPI\u Scatter()
的调用如下所示:

MPI_Scatter(send_vec, num_steps/size, MPI_DOUBLE, recv_vect, 
num_steps/size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
最后,可以使用动态内存分配来避免使用堆栈存储大型阵列。此外,可以减少分配的空间以减少内存占用:

num_steps=(num_steps/size)*size;
double* send_vec=NULL;
double* recv_vec=NULL;
if(rank==0){
   send_vec=malloc((num_steps/size)*sizeof(double));
   if(send_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
}
recv_vec=malloc(num_steps*sizeof(double));
if(recv_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}

...

if(rank==0){
   free(send_vec);
}
free(recv_vec);

我工作。非常感谢。您能解释一下为什么接收大小必须是:num_步数/大小吗?是因为我正在接收我发送的所有内容吗?如中所述,参数
sendcount
必须是“发送到每个进程的元素数”,而
recvcount
必须是“接收缓冲区中的元素数”。如果将类型为
double
num\u steps/size
元素发送到每个进程,每个进程将接收类型为
double
num\u steps/size
。另请参见关于
MPI\u Scatter()
与sendcount关联的类型签名的第160页,根目录下的sendtype必须等于所有进程上与recvcount、recvtype关联的类型签名(但是,类型映射可能不同)。这意味着发送的数据量必须等于接收的数据量,在每个进程和根进程之间成对。发送方和接收方之间仍然允许使用不同类型的映射。
num_steps=(num_steps/size)*size;
double* send_vec=NULL;
double* recv_vec=NULL;
if(rank==0){
   send_vec=malloc((num_steps/size)*sizeof(double));
   if(send_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
}
recv_vec=malloc(num_steps*sizeof(double));
if(recv_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}

...

if(rank==0){
   free(send_vec);
}
free(recv_vec);