深入解析Linux下MPI实现——MPICH3 (linux mpich3)
MPI(Message Passing Interface)是一种并行计算的标准,可以使多台计算机在网络上互相通信,共同协同完成某种复杂的计算任务。它已经成为高性能计算领域中必不可少的工具,被广泛应用于天气预报、气候模拟、分子动力学模拟等众多科学计算领域。Linux作为一个开源操作系统,其上的MPI实现也是广受欢迎的,MPICH3便是其中的佼佼者。
1. MPICH3的概述
MPICH3是一款高性能的MPI实现,在众多MPI实现中,它是最为流行的一个。它不仅能够实现不同节点之间的进程通信,还能够实现节点内部的进程通信。此外,MPICH3还支持多种硬件环境(例如多核、多节点、GPU等),可运行在多种操作系统上,包括Linux、Windows、Mac OS等。
MPICH3是基于MPICH2发展而来的,最新版本号是3.4.1。它不仅继承了前一版本的优点,还进行了一系列的性能优化和功能增强。目前,MPICH3的主要工作是进一步提高性能、支持多种架构和深度集成其他HPC(High Performance Computing)工具。
2. MPICH3的安装和配置
MPICH3的安装比较简单,只需下载tar包,解压后进入解压目录执行configure、make和make install命令即可。配置命令如下:
./configure –prefix=/usr/local/mpich-3.4.1
make && make install
完成安装后需要进行一些设置。需要将mpich安装路径添加到环境变量中:
export PATH=$PATH:/usr/local/mpich-3.4.1/bin
然后,需要将节点的hostname添加到hosts文件中,以保证节点之间可以互相访问:
echo “10.0.0.2 node2” >> /etc/hosts
echo “10.0.0.3 node3” >> /etc/hosts
需要配置MPI环境变量,具体实现方式如下:
export MPI_HOME=/usr/local/mpich-3.4.1
export PATH=$MPI_HOME/bin:$PATH
export LD_LIBRARY_PATH=$MPI_HOME/lib:$LD_LIBRARY_PATH
3. MPICH3的基本用法
一旦完成了安装和配置,便可尝试使用MPICH3进行进程通信。MPI程序由多个进程组成,每个进程之间通过MPI库函数进行通信。MPI库函数由C、C++和Fortran等不同语言的接口,用户可根据自己的需要选择对应的接口。
一个简单的MPI程序如下所示:
#include
#include
int mn(int argc, char *argv[]) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf(“Hello world, I am %d of %d\n”, rank, size);
MPI_Finalize();
return 0;
}
其中,MPI_Init初始化MPI环境;MPI_Comm_rank获取进程的排名;MPI_Comm_size获取进程总数;MPI_Finalize在程序运行结束前清理MPI环境。
在执行MPI程序时需要注意,需要使用mpirun命令启动MPI程序,并指定进程数。例如:
mpirun -np 4 ./helloworld
其中-np表示进程数,./helloworld表示MPI程序的可执行文件名称。
4. MPICH3的高级用法
除了基本用法,MPICH3还支持一些高级的特性,帮助用户更好地优化并行计算性能。
4.1 进程亲和性
进程亲和性(Process Affinity)是指CPU核心与进程之间的绑定关系,它影响进程的性能。如果进程所运行的CPU核心与其存储器绑定关系不好,将会降低程序的性能。为此,MPICH3提供了一种进程亲和性设置方式,可以将进程与CPU核心进行绑定。具体实现方式如下:
MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
int rank, status, provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &provided);
if (provided != MPI_THREAD_SERIALIZED){
printf(“MPI_Init_thread fled, thread support not avlable\n”);
MPI_Abort(MPI_COMM_WORLD, 1);
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
status = bind_to_core(rank);
if (status){
printf(“Task %d: bind_to_core fled with error %d\n”, rank, status);
MPI_Abort(MPI_COMM_WORLD, 1);
}
其中,bind_to_core(rank)是一个自定义函数,它将进程与一个CPU核心绑定。
4.2 原子操作
原子操作(Atomic Operation)是指在多线程并行操作时,一旦有一个线程开始访问共享资源,其他线程就不能再访问该资源的操作方式。MPICH3提供了一种利用原子操作实现互斥的方式,帮助用户更好地进行并行计算。具体实现方式如下:
MPI_Win win;
MPI_Win_create(&my_int, sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);
MPI_Win_lock_all(0, win);
MPI_Fetch_and_op(&one, &result, MPI_INT, 0, 0, MPI_SUM, win);
MPI_Win_unlock_all(win);
其中,MPI_Win_create创建一个共享内存窗口;MPI_Win_lock_all锁定窗口;MPI_Fetch_and_op执行一个原子操作(将变量one的值累加到result变量中,并返回result变量的值);MPI_Win_unlock_all解锁窗口。
5. 结论