下面的程序不能执行,我只是在编译器里面写的笔记,但是思路是对的
#include<mpi.h>
#include<stdio.h>
double f(double x)
{
return 2*x+2.3;
}
double trap(double left_endpt,double right_endpt,int trap_count,double base_len)
{
double estimate,x;
int i;
estimate=(f(left_endpt)+f(right_endpt))/2.0;
for(i=1;i<=trap_count-1;i++)
{
x=left_endpt+i*base_len;
estimate+=f(x);
}
estimate*=base_len;
return estimate;
}
/*大部分MPI实现只允许0号进程访问标准输入,
所以这里我们用0号进程来实现数据的输入,(优化)使用集合通信
首先是最直接的,然后再用集合通信里的广播函数MPI_Bcast函数
*/
void get_input1(int my_rank,int comm_sz,double* a,double* b,int* n)
{
int dest;
if(my_rank==0)
{
printf("please input a,b,n");
scanf("%f%f%d",a,b,n);
for(dest=1;dest<comm_sz;dest++)
{
MPI_Send(a,1,MPI_DOUBLE,dest,0,MPI_COMM_WORLD);
MPI_Send(b,1,MPI_DOUBLE,dest,0,MPI_COMM_WORLD);
MPI_Send(n,1,MPI_INT,dest,0,MPI_COMM_WORLD);
}
}
else
{
MPI_Recv(a,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD);
MPI_Recv(b,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD);
MPI_Recv(n,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
}
void get_input2(int my_rank,int comm_sz,double* a,double* b,int* n)
{
int dest;
if(my_rank==0)
{
printf("please input a,b,n");
scanf("%f%f%n",a,b,n);
}
MPI_Bcast(a,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
MPI_Bcast(b,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
MPI_Bcast(n,1,MPI_INT,0,MPI_COMM_WORLD);
}
void build_mpi_type(double* a,double* b,int* n,MPI_Datatype* input_mpi_t_p)
{
int array_of_blocklength[3]={1,1,1};
MPI_Datatype array_of_types[3]={MPI_DOUBLE,MPI_DOUBLE,MPI_INT};
MPI_Aint array_of_displacements[3]={0};
MPI_Aint a_addr,b_addr,n_addr;
MPI_Get_address(&a,&a_addr);
MPI_Get_address(&b,&b_addr);
array_of_displacements[1]=b_addr-a_addr;
MPI_Get_address(&n,&n_addr);
array_of_displacements[2]=n_addr-a_addr;
MPI_Type_create_struct(3,array_of_blocklength,array_of_displacements,array_of_types,input_mpi_t_p);
MPI_Type_commit(input_mpi_t_p);//在使用通信函数input_mpi_t之前,必须先用一个函数调用去指定他
//上述函数允许MPI实现为了在通信函数内使用这一数据类型,优化数据类型的内部表达
}
void get_input3(int my_rank,int comm_sz,double* a,double* b,int* n)
{
MPI_Datatype input_mpi_t;
build_mpi_type(a,b,n,,&input_mpi_t);
if(my_rank==0)
{
printf("please input a,b,n");
scanf("%f%f%d",a,b,n);
}
MPI_Bcast(a,1,input_mpi_t,0,MPI_COMM_WORLD);
MPI_Type_free(&input_mpi_t);
//在构造新的数据类型时,mpi可能要再内部分配额外的空间,因此当我们使用新的数据类型时可以调用一个函数去释放额外的存储空间
}
int main(void)
{
int my_rank,comm_sz,n=1024,local_n;
double a=0.0,b=3.0,h,local_a,local_b;
double local_int,total_int;
int source;
MPI_Init(NULL,NULL);//通信子初始化
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&comm_sz);
get_input1(my_rank,comm_sz,&a,&b,&n);
//输入函数有三种写法
h=(b-a)/n;
local_n=n/comm_sz;
local_a=a+my_rank*local_n*h;
local_b=local_a+local_n*h;
local_int=trap(local_a,local_b,local_n,h);
/*if(my_rank!=0)
{
MPI_Send(&local_int,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD);
}
else
{
total_int=local_int;//0号进程自身的面积
for(source=1;source<comm_sz;source++)
{
MPI_Recv(&local_int,1,MPI_DOUBLE,sorce,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
total+=local_int;
}
}*/
//使用集合函数可以写成
MPI_Reduce(&local_int,&total_int,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
if(my_rank==0)
{
printf("在划分%d个小梯形,边界为%lf和%lf,我们预测的面积为%f",n,a,b,total_int);
}
MPI_Finalize();
return 0;
}