5题每题20分
1.1)简述MPI 6个函数格式定义,作用,参数含义。
MPI简介:消息传递接口的标准,用于开发基于消息传递的并行程序,目的是为用户提供一个实际可用的、可移植的、高效和灵活的消息传递接口库,能够在PC Windows和所有主要的Unix工作站以及并行机上实现。MPI是一个库,不是一种语言,实现并行必须依托于某种语言:FORTRAN,C MPI主要函数:
MPI_Init,初始化函数:MPI程序通过调用MPI_Init函数进行MPI环境,并完成所有的初始化工作,这个函数通常是MPI程序的第一个函数调用。 格式如下: int MPI_Init( int *argc, char ***argv )
MPI_Finalize,结束函数:MPI通过调用MPI_Finalize函数从MPI环境中退出,它是MPI程序的最后一个MPI函数调用,否则程序的执行结果是不可预知的。 格式如下: int MPI_Finalize(void) ;
MPI_Comm_rank,获取进程的编号:MPI程序通过MPI_Comm_Rank函数调用获取当前进程在指定通信域中的编号,有了该编号,不同的进程就可以将自身和其他进程区分开来,从而实现进程间的并行和合作。
格式如下:nt MPI_Comm_rank(MPI_Comm comm, int *rank)
MPI_Comm_size,获取指定通信域的进程数:MPI通过调用MPI_Comm_size函数获取指定通信域的进程个数,进程可根据它来确定自己应该完成的任务比例。 格式如下:int MPI_Comm_size(MPI_Comm comm, int *size)
MPI_Send消息发送函数:MPI_Send函数用于发送一个消息到目标进程。其格式如下: int MPI_Send( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm_comm)
buf : 消息发送的起始地址 count :发送消息的数量 datatype: 发送数据的类型 dest: 标识目标进程
tag: 发送消息时打上的标签 comm: 通信类型
MPI_Recv,消息接收:MPI_Recv函数用于从指定进程接收一个消息,格式如下:
int MPI_Recv( void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm, comm, MPI_Status *status ) buf : 消息接收后存放地址 count : 接收数量
datatype : 接收数据类型 source : 发送消息的进程 tag : 消息的标签 comm : 通信类型 status : 接收状态
1.2)举例简单的应用解释如何通信。
每个进程会属于一个或多个通信域。
1
一个简单的例子 /* simple.c */
#include “mpi.h” /*MPI头文件*/ #include
int rank, size, tag = 1 ; int senddata, recvdata ; MPI_Status status ;
MPI_Init( &argc, &argv ) ; /*MPI的初始化*/
MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; /*该进程的编号 */ MPI_Comm_size( MPI_COMM_WORLD, &size ); /* 总的进程数目*/
if ( rank == 0 ){
int senddata, recvdata ; MPI_Status status ;
MPI_Init( &argc, &argv ) ; /*MPI的初始化*/
MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; /*该进程的编号 */ MPI_Comm_size( MPI_COMM_WORLD, &size ); /* 总的进程数目*/ if ( rank == 0 ){ senddata = 9999 ;
MPI_Send( &senddata, 1, MPI_INT, 1, tag, MPI_COMM_WORLD ) ; /* 发送数据到进 程1 */ }
if ( rank == 1 ){
MPI_Recv( &recvdata, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status); /*从进程0接收数据*/ }
MPI_Finalize() ; /*MPI的结束函数*/ return (0) ; }
另一个例子
实现 sum( a + b ),并且把求和结果打印出来。这里 a, b 都是n维空间的向量,并且每个元素都为整数。
#include “mpi.h” /*MPI头文件*/ #include
2
int rank, size, i, tag = 1 ; int *a, *b, n; n = 100 ;
a = (int*)malloc( sizeof( int ) * n ) ; b = (int*)malloc( sizeof( int ) * n ) ; for(i = 0 ; i < n ; i++){ a[i] = 1 ; b[i] = 2 ; }
MPI_Status status ;
MPI_Init( &argc, &argv ) ; /*MPI的初始化*/
MPI_Comm_size( MPI_COMM_WORLD, &size ); /* 总的进程数目*/ int nSize = n / size ;
MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; /*该进程的编号 */ if( rank != (size - 1) ){
int sum = 0 ;
for( i = 0 ; i < nSize ; i++ ){
sum += a[i + rank * nSize ] + b[ i + rank * nSize ] ; }
MPI_Send( &sum, 1, MPI_INT, (size-1), tag, MPI_COMM_WORLD ) ; /* 发送求和数据到进程(size-1) */
}else{
int sum = 0, total = 0 ;
for( i = (size - 1) * nSize ; i < n ; i++ ){ sum += a[i] + b[i] ; }
total += sum ;
for( i = 0 ; i < (size - 1) ; i++ ){
MPI_Recv( &sum, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &status); /*从各个进程接收部分求和数据*/
total += sum ; }
printf( \ }
MPI_Finalize() ; /*MPI的结束函数*/ return (0) ; }
3
2.1)通过MPI如何实现2个矢量相加。
/* simple.c */
#include
int rank, size, tag = 1 ; int *a, *b , n = 100 ;
a = (int*)malloc( sizeof( int ) * n ) ; b = (int*)malloc( sizeof( int ) * n ) ; int i ;
for( i = 0 ; i < n ; i++ ){ a[i] = 1 ; b[i] = 2 ; }
MPI_Status status ;
MPI_Init( &argc, &argv ) ; /*MPI的初始化*/
MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; /*该进程的编号 */ MPI_Comm_size( MPI_COMM_WORLD, &size ); /* 总的进程数目*/
int nSize = n / size ; int sum ;
if( rank < (size -1) ){ sum = 0 ;
for( i = 0 ; i < nSize ; i++ ){ sum += a[i] + b[i] ; } }else{
sum = 0 ;
for( i = nSize * (size - 1) ; i < n ; i++ ){ sum += a[i] + b[i] ; } }
printf(\
MPI_Finalize() ; /*MPI的结束函数*/ return (0) ;
4
}
2.2)通过MPI如何实现2个矢量相乘。
#include
int rank, size; int n = 100 ; int i ;
MPI_Status status ;
MPI_Init( &argc, &argv ) ;
MPI_Comm_size( MPI_COMM_WORLD, &size ); int nSize = n / size ;
MPI_Comm_rank( MPI_COMM_WORLD, &rank ) ; int *a, *b ;
a = (int*)malloc( sizeof(int) * n ) ; b = (int*)malloc( sizeof(int) * n ) ;
int( i = 0 ; i < n ; i++ ){ a[i] = 1 ; b[i] = 2 ; }
int tag = 1 ;
if( rank != (size - 1) ){ int sum = 0 ;
for( i = 0 ; i < nSize ; i++ ){
sum += a[rank * nSize + i]* b[rank * nSize + i]; }
MPI_Send( &sum, 1, MPI_INT, (size-1), tag, MPI_COMM_WORLD ) ; }else{
int sum = 0, total = 0 ;
for( i = (size - 1) * nSize ; i < n ; i++ ){ sum += a[i] * b[i]; }
total += sum ;
for( i = 0 ; i < (size - 1) ; i++ ){
MPI_Recv( &sum, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &status);
total += sum ; }
5