原本以为,MPI天生只能在Linux上运行。但这次却发现了Intel MPI Library 这个好用的东西。基本不需要设置,安上之后,用自己能登录windows的帐号和密码注册就行了。虽然不是局域网上的机器,但也可以让我的双核CPU达到100%(平时开个Matlab什么的都才是50%,软件优化真是关键啊)。
FOX算法有一些恶心的要求:输入的矩阵必须是方阵,而且进程必须为平方数,方阵必须能均匀划分给每个进程。其实方阵的条件并不一定必须,只是会增加编程复杂性。
MPI中,虽然最精华的就6条语句,但仅用这6条,还是比较麻烦的。使用一些高级语句,能提高程序性能或是简化代码。
MPI_Bcast,这个是必须要提的。能把这样的语句 if (task_id == root) { send to child_id } else { recieve from root} 仅用个bcast就替换了。
MPI_Isend/MPI_Irecv是异步发送和接收的语句,显然比MPI_Send/MPI_Recv这样的阻塞语句更可能提高性能。另外,还可以避免循环死锁。当然,避免循环死锁的方法还有使用奇偶法、MPI_Sendrecv等。
虽然,理解MPI_Cart_create等一系列的笛卡尔结构操作还是有些难度的,但却是十分有用的进程逻辑功能划分方法。特别在FOX算法中,每行是个通信子域,每列也是。这样就会有n+n个子域(尽管有划分重叠),每个域的进程都仅与域中的其它进程有信息交换,这样仅用bcast一语就能传完数据。
以下是代码。比较简单。就不说明了。
// MatrixMulFox.cpp
// Jarod 2007.12.3
#include "mpi.h"
#include
#include
#include
const int root_id = 0;
const int max_procs_size = 16;
int main(int argc,char *argv[])
...{
double start_time, end_time, time;
int procs_id, procs_size;
MPI_Status status;
MPI_Request reqSend, reqRecv;
MPI_Init(&argc,&argv);
start_time = MPI_Wtime();
MPI_Comm_size(MPI_COMM_WORLD,&procs_size);
MPI_Comm_rank(MPI_COMM_WORLD,&procs_id);
// 参数检查
int N=0;
...{
for (int i=1; i(procs_size)));
const int n = N / procs_size_sqrt;
const int n_sqr = n*n;
if (procs_size<4 || procs_size> max_procs_size) ...{
printf("The fox algorithm requires at least 4 processors and at most %d processors. ",
max_procs_size);
MPI_Finalize();
return 0;
}
if (procs_size_sqrt*procs_size_sqrt != procs_size ) ...{
printf("The number of process must be a square. ");
MPI_Finalize();
return 0;
}
if (N % procs_size_sqrt !=0) ...{
printf("N mod procs_size_sqrt !=0 ");
MPI_Finalize();
return 0;
}
//初始化矩阵
int * A = new int[n_sqr];
int * B = new int[n_sqr];
int * C = new int[n_sqr];
int * T = new int[n_sqr];
for (int i=0; i