分类: 云计算
2012-07-10 12:16:48
一般MPI程序
所有的MPI程序有以下通用的结构:
1、包含MPI头文件;
2、变量声明;
3、初始化MPI环境;
4、计算以及MPI通信调用;
5、关闭MPI通信。
MPI头文件包含MPI描述的定义以及函数原型。
之后是变量声明,每个进程调用一个MPI例程来初始化消息传递环境。所有的MPI通信例程的调用必须在初始化之后。
最后在程序结束前,每个进程都必须调用一个例程来终止MPI。在终止例如调用后不能用MPI例程被调用。注意任何进程在执行时不遵循这个约定的话,程序会表现为挂起。
MPI头文件
包含MPI函数/子例程的原型、宏定义、特殊常量、MPI使用的数据类型。C语言中使用#include
MPI命名规范
所 有MPI项(例程、常量、类型等)都由MPI_开头来避免冲突。C语言里函数名以大写开头,其余为小写,比如MPI_Init。MPI常量均为大写,例如 MPI_COMM_WORLD。特殊定义的类型对应于许多MPI项,类型名和函数命名一样,例如:MPI_Comm对应于一个MPI类型 communicator。
MPI例程和返回值
在C里MPI例程被实现为函数。通常一个错误码会返回,用于测试例程是否成功。例如:
int err;
err = MPI_Init(&argc, &argv);
MPI_SUCCESS表示例程成功运行:
if (err == MPI_SUCCESS) {
...
}
MPI句柄
MPI定义并维护与通信相关的它自己的内部数据结构。你通过句柄引用这些数据结构。句柄通过各种MPI调用返回,并可作为其它MPI调用的参数。
在C语言里,句柄是指向特定数据类型的指针。数组以0开始索引。
MPI 数据类型
MIP提供了它自己的引用数据类型,对应于C的各种基本数据类型。变量通常声明为C类型,MPI类型名用于MPI例程的参数。
MPI隐藏了数据类型表示的细节,比如浮点数的表示。这是实现考虑的事情。
MIP允许异构环境下表示的自动转换。
作为一个通用规则,接收的MPI数据类型必须与发送时指定的MPI数据类型匹配。
此外,MPI允许基于基本类型构建任意数据类型。
C语言的基本MPI数据类型
MPI数据类型 | C类型 |
---|---|
MPI_CHAR | signed char |
MPI_SHORT | signed short int |
MPI_INT | signed int |
MPI_LONG | signed long int |
MPI_UNSIGNED_CHAR | unsigned char |
MPI_UNSIGNED_SHORT | unsigned short int |
MPI_UNSIGNED | unsigned int |
MPI_UNSIGNED_LONG | unsigned long int |
MPI_FLOAT | float |
MPI_DOUBLE | double |
MPI_LONG_DOUBLE | long double |
MPI_BYTE | (none) |
MPI_PACKED | (none) |
C语言的特殊MPI数据类型
例如:
1、MPI_Comm:通信者;
2、MPI_Status:MPI调用的状态信息;
3、MPI_Datatype
这些数据类型可以用于变量声明,例如:
MPI_Comm some_comm;
初始化MPI
任何MPI程序里的第一个MPI例程调用必须是初始化例程MPI_Init。它建立MPI环境。出错时会返回一个错误码。它只能被调用一次。
int err;
err = MPI_Init(&argc, &argv);
通信者(Communicators)
表示可以和另一个进程通信的一组进程的句柄。
对于所有点对点通信和收集操作,都需要通信者名:
1、发送和接收调用里指明的通信者必须同意这次通信发生;
2、只当进程共享同一个通信者时,进程才可以通信。
可以有许多通信者,且某个进程可以是许多不同的通信者里的一个成员。在每个通信者里,进程被连续编号(以0开始)。这个标识号作为通信者里的进程的秩(rank):
1、秩也被用于指明发送和接收调用里的源和目标。
2、如果进程属于多个通信者,它的各个秩可以不同。
MPI自动提供一个基本的通信者MPI_COMM_WORLD。这由所有的进程组成。使用MPI_COMM_WORLD可以让每个进程和任何其它进程通信。你可以定义额外的通信者,包含可用进程的子集。
得到通信者的信息:秩
MPI_Comm_rank用于确定通信者里某个进程的秩。
1、秩是连续的,且从0开始。
2、在不同的通信者里,某个进程可能有不同的秩。
C函数原型:
int MPI_Comm_rank(MPI_Comm comm, int *rank);
参数comm是通信者,你可以使用MPI_COMM_WORLD,也可以使用自己定义的(MPI_Comm some_comm;)。
得到通信者的信息:尺寸
MPI_Comm_size用于获得通信者里的进程数。
C函数原型:
int MPI_Comm_size(MPI_Comm comm, int *size);
1、参数comm为通信者;
2、参数size是返回的整型变量的地址。
终止MPI
MPI_Finalize:
1、清除所有MPI数据结构,取消未完成的操作,等等。
2、必须在所有进程里调用。如果任何进程不遵守这个规则,它将表现为挂起。
一旦MPI_Finalize被调用,(包括MPI_Init在内的)所有其它MPI例程都不能被调用。
例:
int err;
err = MPI_Finalize();
样例程序
#include
#include
void main(int argc, char *argv[]) {
int myrank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Processor %d of %d: Hello World!\n", myrank, size);
MPI_Finalize();
}
上面的代码使用的预定义的通信者MPI_COMM_WORLD;且没有测试例程的错误状态。
编译:
mpicc rank_size.c -o rank_size
运行:
$ mpirun -np 4 ./rank_size
Processor 0 of 4: Hello World!
Processor 3 of 4: Hello World!
Processor 1 of 4: Hello World!
Processor 2 of 4: Hello World!