c语言和fortran并行程序入门(2)


前言

今天用fortran写了一个累加求和的程序,即:输入一个值,可以并行对程序累加求和,我相信这个程序可以帮新手了解fortran并行程序的结构。
然后想结合C语言的对应相同结构的代码探讨一下C和fortran的共同点。


一、C语言并行程序

代码如下:

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

double f(double a)  
{
	return 3*a*a+2*a;
}
int main(int argc, char * argv[])
{
	int done=0,n,myid,numprocs,i;
	double mypi,pi,sum;
	double startwtime,endwtime;
	int namelen;
	char processor_name[MPI_MAX_PROCESSOR_NAME];
 
	MPI_Init(&argc,&argv);
	MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
	MPI_Comm_rank(MPI_COMM_WORLD,&myid);
	MPI_Get_processor_name(processor_name,&namelen);
	fprintf(stderr,"Process %d on %s\n",myid,processor_name);
	fflush(stderr);
	n=0;
    if(myid==0)
    {
        printf("输入一个数字不超过:(0退出)");
        fflush(stdout);
        scanf("%d",&n);
        startwtime=MPI_Wtime();
    }
    MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);  
    if(n==0)
        done=1;
    else
    {
        sum=0.0;
        for(i=myid+1;i<=n;i+=numprocs)
            sum+=f(i);
        mypi=sum;  
        MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
        if(myid==0)     
        {
            printf("结果%.16f\n",pi);
            endwtime=MPI_Wtime();
            printf("时间=%f\n",endwtime-startwtime);
        }
    }
	MPI_Finalize();
	return 0;
}

C语言在调用MPI包内的函数时比较直接,直接写函数名然后传参就可以了。
本程序主要用到MPI的函数是MPI_BcastMPI_Reduce
其中MPI_Bcast 的作用是将变量n广播给所有线程,其函数范式如下

int MPI_Bcast(
	void * data_p;    //通信缓冲区的起始地址(可变)
	int count;		//通信缓冲区的数据个数
	MPI_Datatype datatype;  //通信消息缓冲区中的数据类型
	int source_proc;		//发送广播的根的序列号
	MPI_Comm comm;			//通信子
);

MPI_Reduce的函数范式为

int MPI_Reduce(
void *input_data,   //指向发送消息的内存块的指针 
void *output_data, //指向接收(输出)消息的内存块的指针 
int count,			//数据量
MPI_Datatype datatype,//数据类型
MPI_Op operator,	//规约操作
int dest,			//要接收(输出)消息的进程的进程号
MPI_Comm comm		//通信器,指定通信范围
);

MPI_Reduce的主要用处就是把发送消息内存块的指针,发送到接受消息内存块的指针,以此用来实现进程的通信

在本代码中,先用以下命令广播变量n

MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);  

然后对数据进行计算,求出结果sum,并用Reduce将结果传递给pi,可以看到只有my_id为0时才可以执行输入输出操作,也就是进程号为0的进程负责广播变量和输出结果。

二、Fortran并行程序

代码如下:

program MPI_parallel
  use mpi
  implicit none
  integer, parameter :: rk = 8
  integer :: i, n_limit, ierr, numprocs, myid, c1, c2, c_rate
  real(kind=rk) :: pi, picalc
  call MPI_INIT(ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
  call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
  if(myid == 0) then
     print *, "n_limit="
     read(*,*) n_limit
  end if
  call MPI_BCAST(n_limit, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
  pi = 0.0
  call system_clock(c1, c_rate)
  do i = myid + 1, n_limit, numprocs
     pi = pi + 3*i*i+2*i
  end do
  call MPI_REDUCE( pi, picalc, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD, ierr )
  picalc = picalc
  call system_clock(c2, c_rate)
  if(myid == 0) then
     write(*,*) picalc, real(c2-c1)/real(c_rate), numprocs
  end if
  call MPI_FINALIZE(ierr)
end program MPI_parallel

首先,fortran的导包是use mpi,然后同样的,为了输出结果,需要指定my_id为0的线程作为广播进程和将结果规约的进程。
但是在调用MPI函数时,前面需要加call,这是因为fortran在调用外部库的时候,需要用call来声明。

总结

总体而言,两程序的结构没有太大区别。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值