【问题标题】:openmpi for c++: rank changes inside function apparently without reason.c++的openmpi:函数内部的排名变化显然是没有理由的。
【发布时间】:2014-11-20 18:03:12
【问题描述】:

以下代码产生粘贴在下面的输出

#include "mpi.h"
#include <stdio.h>

#define NUM 5
#define TRANSACTIONS 1

main(int argc, char *argv[])  {
int numtasks, rank, dest, source, rc, count, tag=1;  
char outmsg[] = "Hello World, today is a not so fantastic day for programmers";
char inmsg[20] = "-------------------";
MPI_Status Stat[2];

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

char* baseaddr;

if (rank == 0) {
  dest = 1;
  source = 1;
  printf("a) I am: %d\n", rank);
  rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("b) I am: %d\n", rank);
  baseaddr=outmsg+5;
  //rc = MPI_Send(outmsg+5, NUM, MPI_CHAR, dest, 10, MPI_COMM_WORLD);
  rc = MPI_Send(baseaddr, NUM, MPI_CHAR, dest, 10, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  //rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
  printf("c) I am: %d\n", rank);
  } 

else if (rank == 1) {
  dest = 0;
  source = 0;
  printf("d) I am: %d\n", rank); 
  baseaddr = inmsg+5;
  //rc = MPI_Recv(inmsg+5, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
  rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat[0]);
  printf("e) I am: %d\n", rank);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 10, MPI_COMM_WORLD, &Stat[1]);
  //rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
  printf("f) I am: %d\n", rank);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  }


for(int i=0; i<=TRANSACTIONS; ++i){
    rc = MPI_Get_count(&Stat[i], MPI_CHAR, &count);
    printf("Task %d: Received %d char(s) from task %d with tag %d \n",
           rank, count, Stat[i].MPI_SOURCE, Stat[i].MPI_TAG);
}

MPI_Finalize();
}

这里是输出:

d) I am: 1
e) I am: 1
INBUFFER OF WORKER 1: Hello--------------
f) I am: 1
a) I am: 0
OUTBUFFER OF WORKER 0: Hello World, today is a not so fantastic day for programmers
b) I am: 0
OUTBUFFER OF WORKER 0: Hello World, today is a not so fantastic day for programmers
c) I am: 0
Task 0: Received 0 char(s) from task 4227856 with tag 0 
Task 0: Received 6365232 char(s) from task 0 with tag 4227856 
INBUFFER OF WORKER 1: Hello Worl---------
Task 1: Received 5 char(s) from task 0 with tag 1 
Task 1: Received 5 char(s) from task 0 with tag 10 

这个输出似乎是正确的。现在下面的代码应该会产生相同的输出(据我有限的理解),但最后不会出现这种情况:

#include "mpi.h"
#include <stdio.h>

#define NUM 10
#define TRANSACTIONS 1

main(int argc, char *argv[])  {
int numtasks, rank, dest, source, rc, count, tag=1;  
char outmsg[] = "Hello world, today is a beautiful day.\n";
char inmsg[30] = "-----------------------------";
MPI_Request req;
MPI_Status Stat[TRANSACTIONS];

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

char* baseaddr;

if (rank == 0) {
  dest = 1;
  source = 1;
  rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, 99, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("a) I am: %d\n", rank);
  baseaddr = outmsg + NUM; 
  //rc = MPI_Send(baseaddr, NUM, MPI_CHAR, dest, 999, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("b) I am: %d\n", rank);
  //rc = MPI_Irecv(&inmsg, NUM, MPI_CHAR, source, 2, MPI_COMM_WORLD, &req);
  } 

else if (rank == 1) {
  dest = 0;
  source = 0;
  //rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[0]);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  printf("c) I am: %d\n", rank);
  baseaddr = inmsg + NUM; 
  rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[1]);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  printf("d) I am: %d\n", rank);
  //rc = MPI_Isend(&outmsg, NUM, MPI_CHAR, dest, 2, MPI_COMM_WORLD, &req);
  }

for(int i=0; i<=TRANSACTIONS; ++i){
    rc = MPI_Get_count(&Stat[i], MPI_CHAR, &count);
    printf("Task %d: Received %d char(s) from task %d with tag %d \n",
           rank, count, Stat[i].MPI_SOURCE, Stat[i].MPI_TAG);
}

MPI_Finalize();
}

这里的输出和上面的输出不等价

OUTBUFFER OF WORKER 0: Hello world, today is a beautiful day.

a) I am: 0
OUTBUFFER OF WORKER 0: Hello world, today is a beautiful day.

b) I am: 0
Task 0: Received 0 char(s) from task 6362440 with tag 0 
Task 0: Received 2 char(s) from task 0 with tag 1969314218 
INBUFFER OF WORKER 1: Hello worl-------------------
c) I am: 1
INBUFFER OF WORKER 0: Hello world, today i---------
d) I am: 0
Task 0: Received 10 char(s) from task 0 with tag 99 
Task 0: Received 10 char(s) from task 0 with tag 999 

观察 c) 和 d) 之间的等级似乎从 1 变为 0

c) I am: 1

d) I am: 0

还要注意 INBUFFER OF WORKER 0 输出(而不是 WORKER 1)。

我错过了什么? 谢了

【问题讨论】:

    标签: c++ parallel-processing openmpi


    【解决方案1】:

    您缺少的是您将Stat 声明为一个元素的数组:

    #define TRANSACTIONS 1
    MPI_Status Stat[TRANSACTIONS];
    

    但随后您引用数组Stat[1] 的(越界)第二个元素:

    rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[1]);
    //                                                                  ^^^^^^^
    

    这会导致一些堆栈内存被覆盖,包括持有 rank 的堆栈内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 2012-05-30
      • 1970-01-01
      • 2020-10-17
      • 2021-02-03
      • 2021-08-26
      • 1970-01-01
      相关资源
      最近更新 更多