我在MPI进程之间有一个类似模式通信的管道。其中进程将消息作为管道阶段发送给对方。 以下示例显示了以这种模式进行通信的三个进程。
#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>
//declare stage function
void* testcall(void* d);
int main(int args, char** argv){
int rank, size;
MPI_Status status;
MPI_Init(&args,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(rank==0){
int k;
int x[3] = {10,11,12};
void* data = malloc(sizeof(int));
for( k=0 ; k< 3;k++){
data = &x[k];
MPI_Send(data,4,MPI_BYTE,1,0,MPI_COMM_WORLD);
}
}
if(rank==1){
void* rcv = malloc(sizeof(int));
void* snd = malloc(sizeof(int));
int k;
for( k=0 ; k< 3;k++){
MPI_Recv(rcv,4,MPI_BYTE,0,0,MPI_COMM_WORLD,&status);
snd = testcall(rcv);
int z = *(int *) snd;
printf("RCV 1: %d \n",z);
MPI_Send(&snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);
}
}
if(rank==2){
void* rcv2 = malloc(sizeof(int));
void* snd2 = malloc(sizeof(int));
int k;
for( k=0 ; k< 3;k++){
MPI_Recv(rcv2,4,MPI_BYTE,1,0,MPI_COMM_WORLD,&status);
snd2 = testcall(rcv2);
int z = *(int *) snd2;
printf("RCV 2: %d \n",z);
}
}
MPI_Finalize();
return 0;
}
void* testcall(void* d){
int z = *(int *) d;
int k = z * 2;
void* rslt = malloc(sizeof(int));
rslt = &k;
return rslt;
}
输出:
RCV1:20
RCV1:22
RCV1:24
RCV:2136566600
RCV:2136566600
RCV:2136566600
我的代码有一个问题。从进程0发送到进程1成功,并在打印时给我正确的信息。
从进程1发送到进程2似乎成功,但是当我尝试打印时,它只是一个意外的数字(如上面的输出所示)。
我不明白为什么这两个发送的行为有所不同。 (两者都发送一个由void指针指向的值。为什么第二次发送是错误的)?
请帮忙。答案 0 :(得分:2)
void* testcall(void* d){
int z = *(int *) d;
int k = z * 2;
void* rslt = malloc(sizeof(int));
rslt = &k;
return rslt;
}
此代码不能满足您的期望。 rslt = &k;
行使用rslt
的地址覆盖k
指针的值(您可以在其他几个语句中执行此操作)。首先,这会导致内存泄漏,因为malloc
分配的内存区域的地址会丢失。其次,k
是一个自动(堆栈)变量,其位置将在testcall
返回后用于其他目的。它仅适用于您的情况,因为testcall()
和int z = *(int *) snd;
之间不存在其他函数调用。正确的功能应该是:
void* testcall(void* d){
int z = *(int *) d;
int k = z * 2;
int* rslt = malloc(sizeof(int));
*rslt = k;
return rslt;
}
然后这行来自等级1代码:
MPI_Send(&snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);
snd
本身就是一个指针。您正在发送指针的地址,这就是为什么等级2打印奇怪值的原因。正确的陈述应为:
MPI_Send(snd,4,MPI_BYTE,2,0,MPI_COMM_WORLD);
输出:
RCV 1: 20
RCV 1: 22
RCV 1: 24
RCV 2: 40
RCV 2: 44
RCV 2: 48