C MPI-按订单打印
我试着用C写一个函数,每个处理器都打印自己的数据。 以下是我所拥有的:C MPI-按订单打印,c,parallel-processing,printf,mpi,C,Parallel Processing,Printf,Mpi,我试着用C写一个函数,每个处理器都打印自己的数据。 以下是我所拥有的: void print_mesh(int p,int myid,int** U0,int X,int Y){ int i,m,n; for(i=0;i<p;i++){ if(myid==i){ printf("myid=%d\n",myid); for(n=0;n<X;n++){ for(m=0;m<
void print_mesh(int p,int myid,int** U0,int X,int Y){
int i,m,n;
for(i=0;i<p;i++){
if(myid==i){
printf("myid=%d\n",myid);
for(n=0;n<X;n++){
for(m=0;m<Y;m++){
printf("%d ",U0[n][m]);
}
printf("\n");
}
}
else MPI_Barrier(MPI_COMM_WORLD);
}
}
void打印网格(int p,int myid,int**U0,int X,int Y){
int i,m,n;
对于(i=0;i而言,无法保证来自许多不同进程的消息在到达另一个进程时会以“正确”的顺序到达。这基本上就是这里发生的情况
即使您没有显式发送消息,但当您将某些内容打印到屏幕上时,必须将其发送到本地系统上的进程(mpiexec
或mpirun
)MPI无法知道这些消息的正确顺序,因此它只能在消息到达时打印它们
如果您要求按特定顺序打印邮件,则必须将所有邮件发送到一个列组,该列组可以按您喜欢的顺序打印邮件。只要一个列组执行所有打印,所有邮件的顺序都将正确
应该说,可能会有一些答案,你可以在那里找到,比如说你可以在字符串的末尾放一个换行符,或者使用flush()确保刷新缓冲区,但由于上述原因,这不能保证远程端的排序。MPI标准没有指定如何收集来自不同节点的stdout,并且fflush
没有帮助
如果您需要按顺序打印大型输出,最好的解决方案可能是不要将它们全部收集起来并立即打印,因为这样会在网络上产生流量。
一个更好的解决方案是创建类似于虚拟环的东西,其中每个进程等待来自前一个进程的令牌,打印并发送令牌到下一个进程。当然,第一个进程不必等待,它打印并发送到下一个进程
无论如何,如果输出非常大,在视频上打印输出可能没有意义,您应该按照Jonathan Dursi的建议使用MPI-IO。因此,您可以这样做:
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
MPI_Send(&message, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
printf("1 SIZE = %d RANK = %d MESSAGE = %d \n",size,rank, message);
} else {
int buffer;
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_INT, &buffer);
if (buffer == 1) {
printf("2 SIZE = %d RANK = %d MESSAGE = %d \n",size,rank, message);
MPI_Recv(&message, buffer, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
if (rank + 1 != size) {
MPI_Send(&message, 1, MPI_INT, ++rank, 0, MPI_COMM_WORLD);
}
};
};
MPI_Finalize();
执行后:
$ mpirun -n 5 ./a.out
1 SIZE = 5 RANK = 0 MESSAGE = 999
2 SIZE = 5 RANK = 1 MESSAGE = 999
2 SIZE = 5 RANK = 2 MESSAGE = 999
2 SIZE = 5 RANK = 3 MESSAGE = 999
2 SIZE = 5 RANK = 4 MESSAGE = 999
我的灵感来自于СаааПааааааааааааааааааааа107数据。或者,如果数据的顺序很重要(并且不是太大),建议的方法是将数据全部发送到cpu上(比如秩0),然后cpu会正确格式化数据
对我来说,这似乎有点过分,尤其是当数据可以是可变长度字符串时,这通常是std::cout出于调试和开发目的,您可以在单独的终端中运行每个进程,因此它们在自己的终端中打印:
mpirun-np n xterm-hold-e./output
n
:处理器数量
-保持
:在程序完成后保持xterm打开。
输出
:MPI可执行文件的名称Wesley Bland是对的;由于缓冲的原因,没有通用的方法可以这样做。我一直使用与示例代码中相同的方法,在小输出的情况下,它通常工作得很好,但没有保证,而且肯定不会以相当大的数量工作s输出(>大于单个I/O缓冲区)。最好是使用MPI-IO写入文件(例如),但同样需要注意的是,大量数据最好以二进制格式写入。还要注意,您在MPI\u COMM\u WORLD
中调用MPI\u Barrier
,并且在MPI\u COMM\u WORLD
中的每一轮中,都有一个级别的MPI\u Barrier
调用失败。对MPI\u Barrier
的调用不应在条件的else
块中nal构造,即删除else
关键字。+1;fflush(stdout)
当然值得尝试,但是的,没有保证,在一个系统上起作用的可能在另一个系统上不起作用。您在哪里分配“消息”?
#include <iostream>
#include <sstream>
#include <mpi.h>
int mpi_size;
int mpi_rank;
void init_mpi(int argc, char * argv[]) {
MPI_Init(& argc, & argv);
MPI_Comm_size(MPI_COMM_WORLD, & mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, & mpi_rank);
}
void finalize_mpi() {
MPI_Finalize();
}
template<class T, MPI_Datatype MPI_T> class MPIChain{
// Uses a chained MPI message (T) to coordinate serial execution of code (the content of the message is irrelevant).
private:
T message_out; // The messages aren't really used here
T message_in;
int size;
int rank;
public:
void next(){
// Send message to next core (if there is one)
if(rank + 1 < size) {
// MPI_Send - Performs a standard-mode blocking send.
MPI_Send(& message_out, 1, MPI_T, rank + 1, 0, MPI_COMM_WORLD);
}
}
void wait(int & msg_count) {
// Waits for message to arrive. Message is well-formed if msg_count = 1
MPI_Status status;
// MPI_Probe - Blocking test for a message.
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, & status);
// MPI_Get_count - Gets the number of top level elements.
MPI_Get_count(& status, MPI_T, & msg_count);
if(msg_count == 1) {
// MPI_Recv - Performs a standard-mode blocking receive.
MPI_Recv(& message_in, msg_count, MPI_T, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, & status);
}
}
MPIChain(T message_init, int c_rank, int c_size): message_out(message_init), size(c_size), rank(c_rank) {}
int get_rank() const { return rank;}
int get_size() const { return size;}
};
class ChainStream : public MPIChain<int, MPI_INT> {
// Uses the MPIChain class to implement a ostream with a serial operator<< implementation.
private:
std::ostream & s_out;
public:
ChainStream(std::ostream & os, int c_rank, int c_size)
: MPIChain<int, MPI_INT>(0, c_rank, c_size), s_out(os) {};
ChainStream & operator<<(const std::string & os){
if(this->get_rank() == 0) {
this->s_out << os;
// Initiate chain of MPI messages
this->next();
} else {
int msg_count;
// Wait untill a message arrives (MPIChain::wait uses a blocking test)
this->wait(msg_count);
if(msg_count == 1) {
// If the message is well-formed (i.e. only one message is recieved): output string
this->s_out << os;
// Pass onto the next member of the chain (if there is one)
this->next();
}
}
// Ensure that the chain is resolved before returning the stream
MPI_Barrier(MPI_COMM_WORLD);
// Don't output the ostream! That would break the serial-in-time exuction.
return *this;
};
};
int main(int argc, char * argv[]) {
init_mpi(argc, argv);
ChainStream cs(std::cout, mpi_rank, mpi_size);
std::stringstream str_1, str_2, str_3;
str_1 << "FIRST: " << "MPI_SIZE = " << mpi_size << " RANK = " << mpi_rank << std::endl;
str_2 << "SECOND: " << "MPI_SIZE = " << mpi_size << " RANK = " << mpi_rank << std::endl;
str_3 << "THIRD: " << "MPI_SIZE = " << mpi_size << " RANK = " << mpi_rank << std::endl;
cs << str_1.str() << str_2.str() << str_3.str();
// Equivalent to:
//cs << str_1.str();
//cs << str_2.str();
//cs << str_3.str();
finalize_mpi();
}
std::cout << "a" << "b" << "c"" << std::endl
g++-7 -O3 -lmpi serial_io_obj.cpp -o serial_io_obj
mpirun -n 10 ./serial_io_obj
FIRST: MPI_SIZE = 10 RANK = 0
FIRST: MPI_SIZE = 10 RANK = 1
FIRST: MPI_SIZE = 10 RANK = 2
FIRST: MPI_SIZE = 10 RANK = 3
FIRST: MPI_SIZE = 10 RANK = 4
FIRST: MPI_SIZE = 10 RANK = 5
FIRST: MPI_SIZE = 10 RANK = 6
FIRST: MPI_SIZE = 10 RANK = 7
FIRST: MPI_SIZE = 10 RANK = 8
FIRST: MPI_SIZE = 10 RANK = 9
SECOND: MPI_SIZE = 10 RANK = 0
SECOND: MPI_SIZE = 10 RANK = 1
SECOND: MPI_SIZE = 10 RANK = 2
SECOND: MPI_SIZE = 10 RANK = 3
SECOND: MPI_SIZE = 10 RANK = 4
SECOND: MPI_SIZE = 10 RANK = 5
SECOND: MPI_SIZE = 10 RANK = 6
SECOND: MPI_SIZE = 10 RANK = 7
SECOND: MPI_SIZE = 10 RANK = 8
SECOND: MPI_SIZE = 10 RANK = 9
THIRD: MPI_SIZE = 10 RANK = 0
THIRD: MPI_SIZE = 10 RANK = 1
THIRD: MPI_SIZE = 10 RANK = 2
THIRD: MPI_SIZE = 10 RANK = 3
THIRD: MPI_SIZE = 10 RANK = 4
THIRD: MPI_SIZE = 10 RANK = 5
THIRD: MPI_SIZE = 10 RANK = 6
THIRD: MPI_SIZE = 10 RANK = 7
THIRD: MPI_SIZE = 10 RANK = 8
THIRD: MPI_SIZE = 10 RANK = 9