三、MPI实现
5.集合操作通信
(1): MPI_Reduce函数
函数原型:
int MPI_Reduce(
void* input_data_p,
void* output_data_p,
int count,
MPI_Datatype datatype,
MPI_Op operator
int dest,
MPI_Comm communicator){...}
参数解释:
①void* input_data_p
每一个进程要输入的数据存放地。
②void* output_data_p
输出结果的存放地。
③int count
操作次数,注意:如果count>1,那么MPI_Reduce函数可以应用到数组上(配合input_data_p指向一个数组,output_data_p指向一个数组)。
④MPI_Datatype datatype
MPI数据类型。
⑤MPI_Op operator
要执行的操作名。
⑥int dest
MPI将操作过后的结果传入的目的地进程的序号
⑦MPI_Comm communicator
通信子名。
⑧返回值:
错误码。
函数作用:
count=1
时:名为communicator
通信子中所有进程中(包括目的地进程)input_data_p
指向的datatype
类型的数据存放地中的第1
个数据,全部汇集到MPI缓存中,MPI对它们执行operator
操作,得到的结果再传入dest
号进程的output_data_p
指向的区域中。
count=k
时:在count=k-1
的基础上,communicator
通信子中所有进程中(包括目的地进程)intpu_data_p
指向的datatype
类型的数据存放地中的第k
个数据,全部汇集到MPI缓存中,MPI对它们执行operator
操作,得到的结果再传入dest
号进程的output_data_p
指向的区域中的第k
个位置。
(2): MPI_Allreduce函数
与MPI_Reduce函数的区别:
MPI_Reduce函数只会将结果传递给目的地进程,而MPI_Allreduce函数会将结果传递给每一个进程。
函数原型:
int MPI_Allreduce(
void* input_data_p,
void* output_data_p,
int count,
MPI_Datatype datatype,
MPI_Op operator
MPI_Comm communicator){...}
参数解释:
①void* input_data_p
每一个进程要输入的数据存放地。
②void* output_data_p
输出结果的存放地。
③int count
操作次数,注意:如果count>1,那么MPI_Allreduce函数可以应用到数组上(配合input_data_p指向一个数组,output_data_p指向一个数组)。
④MPI_Datatype datatype
MPI数据类型。
⑤MPI_Op operator
要执行的操作名。
⑥MPI_Comm communicator
通信子名。
⑦返回值:
错误码。
函数作用:
count=1
时:名为communicator
通信子中所有进程中intpu_data_p
指向的datatype
类型的数据存放地中的第1
个数据,全部汇集到MPI缓存中,MPI对它们执行operator
操作,得到的结果再传入每一个进程的output_data_p
指向的区域中。
count=k
时:在count=k-1
的基础上,communicator
通信子中所有进程中intpu_data_p
指向的datatype
类型的数据存放地中的第k
个数据,全部汇集到MPI缓存中,MPI对它们执行operator
操作,得到的结果再传入每一个进程的output_data_p
指向的区域中的第k
个位置。
(3)MPI_Op可取的值
6.MPI派生数据类型
(1)背景
用多条消息发送一定量的数据明显比只用一条消息发送等量数据的开销更大。MPI提供了三种手段来整合可能需要多条消息才能交换的数据。①count参数;②派生数据类型;③MPI_Pack与MPI_Unpack函数。目前我们已经能熟练使用count参数,现在我们来了解MPI派生数据类型,至于MPI打包/解包函数暂时用得不多,可以自己去了解。
(2)实现
由于书上说得十分完善与精简,故直接贴上书中的表述,如下:
7.计时
下面这一段代码可用于对一段MPI程序进行计时并报告运行时间:
double local_start,local_finish,local_elapsed,elapsed;
...
MPI_Barrier(comm);//能够确保同一通信子中的所有进程都完成调用该函数之前,没有进程能够返回
local_start = MPI_Wtime();//MPI_Wtime此函数记录之前某一时刻到此时所经历的时间
...
local_finish = MPI_Wtime();//所有MPI_Wtime函数的时间开始时刻在同一进程中是同一时刻
local_elapsed = local_finish-local_start;
MPI_Reduce(&local_elapsed,&elapsed,1,MPI_DOUBLE,MPI_MAX,0,comm);
if(my_rank==0){
printf("%e\n",elapsed);
}
四、终极练习
请结合所学设计一个利用MPI实现的并行归并排序程序,要求如下:
①进程数无限制(数量无上限,可为奇数,也可为偶数);
②关键字数量无限制(可以为奇数,也可以为偶数);
③当进程数为1时,此程序就是一个串行的归并排序;
④以10000个关键字数为输入时,10进程时,并行效率不低于60%。