MPI发送/接收错误
MPI Send/Recv error
我用c++写了一个测试程序,以确保我理解MPI发送/接收是如何工作的(显然我没有)。这个测试运行在4个处理器上。我感兴趣的具体情况是,处理器0将数组"send_n"发送给处理器2,处理器2在数组"recv_s"中接收它。在初始发送之后,数组是正确的(它应该都是5),但是在我做了一些额外的发送/接收之后,数组以某种方式改变了。我哪里做错了?
#include <stdlib.h>
#include <iostream>
using namespace std;
# include "mpi.h"
void passBCs(double recv_n[],double recv_e[],double recv_s[],double recv_w[]);
int getNextProcID(int pID, int direction);
int procID,numProcs;
int gridx=2,gridy=2;
int procGridX=2, procGridY=2;
int main(){
int i,j,k;
int cryptIDs[2]={0,3};
int villusIDs[2]={1,2};
double recv_n[gridx*5],recv_e[gridy*5],recv_s[gridx*5],recv_w[gridy*5];
MPI::Init();
procID=MPI::COMM_WORLD.Get_rank();
numProcs=MPI::COMM_WORLD.Get_size();
if(procID==0){cout<<"MPI Initializedn";}
passBCs(recv_n,recv_e,recv_s,recv_w);
MPI::COMM_WORLD.Barrier();
if(procID==2){
for(i=0;i<10;i++){cout<<"Test Buffer="<<recv_s[i]<<"n";}}
MPI::Finalize();
if(procID==0){cout<<"Test Run Exiting Normallyn";}
}
void passBCs(double recv_n[],double recv_e[],double recv_s[],double recv_w[]){
int i,j,k,nId,eId,sId,wId,n_rId,e_rId,s_rId,w_rId;
int ntag,etag,stag,wtag;
double send_n[gridx*5],send_e[gridy*5],send_s[gridx*5],send_w[gridy*5];
ntag=0;
etag=1;
stag=2;
wtag=3;
if(procID==0){
for(i=0;i<10;i++){
send_n[i]=5;
send_s[i]=1;
send_e[i]=2;
send_w[i]=3;
}}
else{ for(i=0;i<10;i++){
send_n[i]=0;
send_s[i]=0;
send_e[i]=0;
send_w[i]=0;
}}
nId=getNextProcID(procID,0);
eId=getNextProcID(procID,1);
sId=getNextProcID(procID,2);
wId=getNextProcID(procID,3);
n_rId=getNextProcID(procID,2);
e_rId=getNextProcID(procID,3);
s_rId=getNextProcID(procID,0);
w_rId=getNextProcID(procID,1);
if(procID==2){cout<<"South Recv ID="<<n_rId<<"n";}
if(procID==0){cout<<"Proc 0 sending North to "<<nId<<"n";}
MPI::COMM_WORLD.Send(&send_n[0],20,MPI::DOUBLE,nId,ntag);
MPI::COMM_WORLD.Recv(&recv_s[0],20,MPI::DOUBLE,n_rId,ntag);
if(procID==2){
for(i=0;i<10;i++){cout<<"Test Buffer0="<<recv_s[i]<<"n";}}
MPI::COMM_WORLD.Send(&send_e[0],20,MPI::DOUBLE,eId,etag);
MPI::COMM_WORLD.Recv(&recv_w[0],20,MPI::DOUBLE,e_rId,etag);
if(procID==2){
for(i=0;i<10;i++){cout<<"Test Buffer1="<<recv_s[i]<<"n";}}
MPI::COMM_WORLD.Send(&send_s[0],20,MPI::DOUBLE,sId,stag);
MPI::COMM_WORLD.Recv(&recv_n[0],20,MPI::DOUBLE,s_rId,stag);
MPI::COMM_WORLD.Send(&send_w[0],20,MPI::DOUBLE,wId,wtag);
MPI::COMM_WORLD.Recv(&recv_e[0],20,MPI::DOUBLE,w_rId,wtag);
}
int getNextProcID(int pID, int direction){
//Returns the ID number for the processor that is "direction" to the give proc id.
//0=north,1=east,2=south,3=west;
int x_pos,y_pos,nextID;
x_pos=pID%procGridX;
y_pos=pID/procGridY;
if(direction==0){y_pos++;}
if(direction==1){x_pos++;}
if(direction==2){y_pos--;}
if(direction==3){x_pos--;}
if(x_pos<0){x_pos=procGridX-1;}
if(x_pos>=procGridX){x_pos=0;}
if(y_pos<0){y_pos=procGridY-1;}
if(y_pos>=procGridY){y_pos=0;}
nextID=y_pos*procGridY+x_pos;
return nextID;
}
输出为:
MPI Initialized
South Recv ID=0
Proc 0 sending North to 2
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=0
Test Buffer1=5
Test Buffer1=5
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=0
Test Buffer=5
Test Buffer=5
Test Run Exiting Normally
我认为您观察到的错误是由您对文件进行的不一致编辑的不幸组合或对MPI::COMM_WORLD.Send
的count
参数的误解引起的。来自OpenMPI的文档:
void Comm::Send(const void* buf, int count, const Datatype&数据类型,int dest, int tag) const
buf:发送缓冲区的初始地址(选择)。
count:发送的元素个数(非负整数)。
datatype:每个send buffer元素(句柄)的数据类型。
dest: Rank of destination (integer).
tag:消息标签(整数)。
comm: Communicator (handle).
注意,count形参是第三个参数定义的元素个数(不是某种类型无关的大小度量)。显然,您最初在数组中有20个元素,或者您认为count
参数表示以4字节块表示发送缓冲区的大小。无论如何,您的MPI命令涉及20个元素,例如MPI::COMM_WORLD.Send(&send_n[0],20,MPI::DOUBLE,nId,ntag);
。因此,Recv
命令将从数组末尾以外的位置发送的数据写入到目标数组末尾以外的位置!您只是幸运地没有看到段错误(并且再次幸运,因为编译器将您的数组放在彼此旁边,因此您实际上看到了在数组外写入的效果)。我刚刚编译了你的程序,用10
s代替了所有的20
s,它运行得很好(我没有重新发布代码,因为它只是这样一个简单的改变)。
修改后的输出:
MPI Initialized
Proc 0 sending North to 2
South Recv ID=0
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer0=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer1=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Buffer=5
Test Run Exiting Normally
为了避免将来出现这些错误,将数组的大小与传递给Send
命令的count
相结合,例如,通过一些编译时常量或预处理器宏。既然你正在使用c++,为什么不使用std::vector<double>
而不是双数组,其大小可以在发送它们之前运行时确定,无论它们是如何构造的?
- 如何接受 [ENTER] 键作为无效输入并发送错误消息
- 将数据包从C++服务器发送到NodeJs服务器时出现MessagePack解码错误
- 错误:10035 Winsock发送
- SFML UdpSockets没有错误地发送/接收?
- 在 SFML 中使用 TcpSocket 发送数据会导致分段错误
- MPI 发送出现分段错误
- 蓝牙LE:设置字节数组的特征会发送错误的值
- 服务器客户端通过原始数据错误C 发送接收结构
- 如何在C++中使用 ZeroMQ 发送包含数组的结构时解决错误
- 有时将函数作为参数发送时错误
- ATMega328P 和 ESP8266ex 之间的 I2c 通信只能发送 8 个字节,错误?
- 无法找到"断管"错误的原因,同时通过Beast websocket发送连续数据块
- C 错误将参数重新发送到模板函数(矩阵参数)
- 如何将C 编译器错误发送到CMD中的文本文件
- C - 空数对象的初始化发送不良访问错误
- 错误请求,您的浏览器发送了此服务器无法理解的请求 - Qt Websocket 服务器
- 发送 QML 项目列表C++类连接到 QML :M16 错误
- 使用 winsock 库发送 GET HTTP 请求时出现 400 错误请求错误
- Sybase DB 错误:数据库驱动程序错误.发送失败
- c++ WSAEFAULT错误发送整数