历数学习 MPICH2 遇到的坑-程序
如无特别说明,以下对应问题出现在代码注释中。
1. MPI_Send 和 MPI_Recv
这里如果不重新声明 Recv 的目标,则在 Ubuntu 下无法正常 Recv 。
#include "mpi.h"
#include<string.h>
#include<stdio.h>
int main(int argc, char *argv)
{
char message[20];
int myrank;
memset(message, 0, 20);
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 1)
{
printf("randk 0 start ok\n");
strcpy_s(message, 20, "Hello, process 1");
/ 加_s 是因 VS 编译不通过 /
// strcpy(message, "Hello, process 1");
printf("sended :---%s---\n", message);
MPI_Send(message, strlen(message)+1, MPI_CHAR, 0, 99, MPI_COMM_WORLD);
/ 加 1 是因数组最后一位是 \0 表示结束 /
printf("randk 0 finish ok\n");
}
else if (myrank == 0)
{
// char message[20];
/ 这里如果不重新声明,则在 Ubuntu 下无法正常 Recv */
printf("randk 1 start ok\n");
MPI_Recv(message, 20, MPI_CHAR, 1, 99, MPI_COMM_WORLD, &status);
printf("received :---%s---\n", message);
printf("randk 1 finish ok\n");
}
MPI_Finalize();
}
2. 时钟函数
参考 MPI程序例子 -- 时间函数测试
(书上莫名其妙调用不存在的 test.h
真的无语,Windows 里多线程没问题,都是 Success;Linux 中线程为 n 则耗时为 n 秒,不知什么问题)
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void sleep(clock_t wait)
/* 如果不重定义,则 Windows 里没有这个函数,Linux 里默认是只对整数参数返回非零值 */
{
clock_t goal;
goal = wait + clock();
while (goal > clock())
;
}
int main(int argc, char* argv[]) /* 必要的命令行参数 */
{
int err = 0;
double t1, t2;
double tick;
int i, myrank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
t1 = MPI_Wtime(); /* 获得当前时间t1 */
t2 = MPI_Wtime(); /* 获得当前时间t2 */
if (t2 - t1>0.1 || t2 - t1<0.0)
{
/* 若连续两次时间调用得到的时间间隔过大,这里是超过0.1秒,
或者后调用的函数得到的时间比先调用的时间小,则时间调用有错。 */
err++;
fprintf(stderr, "Two successive calls to MPI_Wtime gave strange result:(%f)(%f)\n", t1, t2);
}
/* 循环测试10次,每次循环调用两次时间函数,两次时间调用的时间间隔是1秒。 */
for (i = 1; i<10; i++)
{
t1 = MPI_Wtime(); /* 计时开始 */
sleep(1000); /* 睡眠1秒 */
//sleep(1000000); /* Linux 微秒单位 */
t2 = MPI_Wtime(); /* 计时结束 */
if (t2 - t1 >= (1.0 - 0.01) && t2 - t1 <= 5.0) break;
if (t2 - t1>5.0) break; /* 两次计时得到时间间隔合理,则退出。 */
}
if (i == 10)
{
/* 计时函数不正确 */
fprintf(stderr, "Timer around sleep(1) did not give 1 second;gave %f\n", t2 - t1);
err++;
}
else/* 输出时间间隔 */
fprintf(stderr, "Processor %d:Success,t2-t1= %f\n", myrank, t2 - t1);
tick = MPI_Wtick(); /* 得到一个时钟滴答的时间 */
if (tick>1.0 || tick<0.0)
{
/* 该时间太长或者为负数,则该时间不正确。 */
err++;
fprintf(stderr, "MPI_Wtick gave a strange result: (%f)\n", tick);
}
MPI_Finalize();
return 0;
}
3. Abort 函数
Linux下没问题,输出结果随机顺序。Windows 下 MPI_Abort
会杀掉所有输出,而这不是因为 Windows 反应慢(我为了等这个线程都加了 10 秒富裕时间)。
#include "mpi.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
void sleep(clock_t wait)
{
clock_t goal;
goal = wait + clock();
while (goal > clock())
;
}
int main(int argc, char **argv)
{
int node, size, i;
int masternode = 0;
/* 设置缺省初始值 */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &node);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* 检查参数 */
for (i = 0; i<argc; i++) {
fprintf(stdout, "myid=%d,procs=%d,argv[%d]=%s\n", node, size, i, argv[i]);
}
//if (node == masternode) {
if (node == size - 1) {
/* 由master进程执行退出操作 */
fprintf(stdout, "myid=%d is masternode Abort!\n", node);
sleep(10000);
MPI_Abort(MPI_COMM_WORLD, 100);
//MPI_Barrier(MPI_COMM_WORLD);
/* MPI_Barrier 就可以得到应有的输出 */
}
else {
/* 非master进程等待 */
fprintf(stderr, "myid=%d is not masternode Barrier!\n", node);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
4. 传值函数
在 Linux 上直接就通过了,而且结果正确。在 Windows 上不能输入,没有任何输出,程序死掉了。
#include <stdio.h>
#include "mpi.h"
int main(int argc, char argv)
{
int rank, value, size;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
do {
if (rank == 0) {
fprintf(stderr, "\nPlease give new value=");
/进程0读入要传递的数据/
scanf("%d", &value);
fprintf(stderr, "%d read <-<- (%d)\n", rank, value);
if (size>1) {
MPI_Send(&value, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD);
fprintf(stderr, "%d send (%d)->-> %d\n",
rank, value, rank + 1);
/* 若不少于一个进程 则向下一个进程传递该数据/
}
}
else {
MPI_Recv(&value, 1, MPI_INT, rank - 1, 0, MPI_COMM_WORLD,
&status);
/ 其它进程从前一个进程接收传递过来的数据/
fprintf(stderr, "%d receive (%d)<-<- %d\n", rank, value, rank - 1);
if (rank < size - 1) {
MPI_Send(&value, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD);
fprintf(stderr, "%d send (%d)->-> %d\n",
rank, value, rank + 1);
/若当前进程不是最后一个进程 则将该数据继续向后传递/
}
}
MPI_Barrier(MPI_COMM_WORLD);
/ 执行一下同步 加入它主要是为了将前后两次数据传递分开/
} while (value >= 0);
/ 循环执行 直到输入的数据为负时才退出 */
MPI_Finalize();
}
5. 互相问候
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
void Hello(void);
int main(int argc, char *argv[])
{
int me, option, namelen, size;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &me);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/*得到当前进程标识和总的进程数*/
if (size < 2) {
/*若总进程数小于2 则出错退出*/
fprintf(stderr, "systest requires at least 2 processes");
MPI_Abort(MPI_COMM_WORLD, 1);
}
MPI_Get_processor_name(processor_name, &namelen);
/*得到当前机器名字*/
fprintf(stderr, "Process %d is alive on %s\n", me, processor_name);
MPI_Barrier(MPI_COMM_WORLD);
/*同步*/
Hello();
/*调用问候过程*/
MPI_Finalize();
}
void Hello(void)
/*任意两个进程间交换问候信息 问候信息由发送进程标识和接收进程标识组成*/
{
int nproc, me;
int type = 1;
int buffer[2], node;
MPI_Status status;
MPI_Comm_rank(MPI_COMM_WORLD, &me);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
/*得到当前进程标识和总的进程数*/
if (me == 0) {
/* 进程0负责打印提示信息*/
printf("\nHello test from all to all\n");
fflush(stdout);
}
for (node = 0; node<nproc; node++) {
/*循环对每一个进程进行问候*/
if (node != me) {
/* 得到一个和自身不同的进程标识*/
buffer[0] = me; /*将自身标识放入消息中*/
buffer[1] = node; /*将被问候的进程标识也放入消息中*/
MPI_Send(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD);
/*首先将问候消息发出 */
MPI_Recv(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD, &status);
/*然后接收被问候进程对自己发送的问候消息*/
if ((buffer[0] != node) || (buffer[1] != me)) {
/*若接收到的消息的内容不是问候自己的或不是以被问候方的身份问候自
己 则出错*/
(void)fprintf(stderr, "Hello: %d!=%d or %d!=%d\n",
buffer[0], node, buffer[1], me);
printf("Mismatch on hello process ids; node = %d\n", node);
}
printf("Hello from %d to %d\n", me, node);
/*打印出问候对方成功的信息*/
fflush(stdout);
}
}
}