C 如何检查消息在MPI中是否可用?
是否有办法查看节点是否是邮件的收件人?大概是这样的:C 如何检查消息在MPI中是否可用?,c,mpi,C,Mpi,是否有办法查看节点是否是邮件的收件人?大概是这样的: int-MPI\u HasMessage() 我正在尝试编写一个循环,如果另一个节点找到了解决方案,它会被根节点(rank=0)中断。否则它将继续 for(int i = 0; i < workload; i++) { doWork(); if(MPI_HasMessage()) { MPI_recv(...); } } for(int i=0;i
int-MPI\u HasMessage()
我正在尝试编写一个循环,如果另一个节点找到了解决方案,它会被根节点(rank=0
)中断。否则它将继续
for(int i = 0; i < workload; i++)
{
doWork();
if(MPI_HasMessage())
{
MPI_recv(...);
}
}
for(int i=0;i
您可能会对该功能感兴趣,该功能允许在不实际收到传入消息的情况下检查传入消息
例如,进程0使用MPI_Isend()
向自身发送消息,然后探测它,最后使用MPI_Recv()
接收它
下面的C代码使用MPI ANY源来探测来自通信器中任何进程的消息。它可以通过mpicc main.c-o main-Wall编译,并通过mpirun-np4 main运行
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc,char *argv[])
{
int size, rank;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Status status;
srand(time(NULL));
int r=0;
if(rank==0){
r = rand()%size; // ugly random, not even uniformly distributed
}
MPI_Bcast(&r,1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Request request=MPI_REQUEST_NULL;
if(rank==r){
MPI_Isend(&r,1,MPI_INT,0,0,MPI_COMM_WORLD,&request);
}
if(rank==0){
int flag=0;
// probing the message
while(!flag)
{
// probing on a regular basis, process zero can do anything there
int i;
int coffee=42;
for(i=0;i<1000000;i++){
coffee+=1;
}
MPI_Iprobe( MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &flag, &status );
}
// the status argument retruned by the function could have been used to make sure that
// MPI_Recv receives the probed message. MPI_Get_count( &status, MPI_INT, &count );
// could have been added to retrieve the length of the message
MPI_Recv( &r, 1, MPI_INT,MPI_ANY_SOURCE , 0, MPI_COMM_WORLD, &status );
printf("process 0 got %d\n",r);
}
MPI_Wait(&request, &status);
MPI_Finalize();
return 0;
}
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
整数大小、等级;
MPI_Init(&argc,&argv);
MPI_通信大小(MPI_通信世界和大小);
MPI通信等级(MPI通信世界和等级);
MPI_状态;
srand(时间(空));
int r=0;
如果(秩==0){
r=rand()%size;//随机分布,分布不均匀
}
MPI_Bcast(&r,1,MPI_INT,0,MPI_COMM_WORLD);
MPI\u请求=MPI\u请求\u NULL;
if(秩==r){
MPI Isend(&r,1,MPI INT,0,0,MPI通信世界和请求);
}
如果(秩==0){
int标志=0;
//探究信息
while(!flag)
{
//在常规的基础上进行探测,process zero可以在那里做任何事情
int i;
int=42;
例如(i=0;iFrancis确实对你的问题给出了正确的答案。然而,这实际上是一个例子
你的实际问题是:
如果发现解决方案,如何通知所有流程
这似乎是一个没有简单答案的常见问题,请检查问题和答案
您肯定不需要使用MPI\u Iprobe
,通过MPI\u Irecv
预先发布的消息就可以了。我建议使用非阻塞集合,如中的更多定义所述
#包括
#包括
#包括
最大常数=10000;
const int难度=20000;
int find_stuff()
{
int num_iters=rand()%iter_max;
对于(int i=0;i0;已找到计数--){
MPI_Recv(空、0、MPI_字符、MPI_任意源、停止标记、MPI_通信世界和状态);
printf(“来自%d\n的附加停止”,状态.MPI\u源);
}
返回1;
}
返回0;
}
int main()
{
MPI_Init(NULL,NULL);
整数秩;
MPI通信等级(MPI通信世界和等级);
srand(秩);
MPI请求根目录接收停止;
MPI请求所有接收停止;
if(秩==根){
MPI_Irecv(NULL、0、MPI_字符、MPI_任意源、停止标记、MPI_通信世界和根记录停止);
}否则{
//您可能需要在此处使用额外的通讯器,以避免与其他障碍物发生冲突
MPI Ibarrier(MPI通信世界和所有接收站);
}
而(1){
int found=find_stuff();
如果(找到){
printf(“排名%d发现了一些东西。\n”,排名);
//注意:我们不能将其发布为阻塞,否则reduce会出现死锁
MPI_请求请求;
MPI_Isend(NULL、0、MPI_字符、root、stop_标记、MPI_COMM_WORLD和req);
if(秩!=根){
//我们知道我们将收到自己的停止信号。
//这样可以避免运行另一个无用的迭代
MPI\u等待(&all\u recv\u stop,MPI\u STATUS\u IGNORE);
MPI_Reduce(&found,NULL,1,MPI_INT,MPI_SUM,root,MPI_COMM_WORLD);
MPI\u等待(&req,MPI\u状态\u忽略);
打破
}
MPI\u等待(&req,MPI\u状态\u忽略);
}
if(秩==根){
如果(找到前向停止(&root\u recv\u停止,&all\u recv\u停止)){
打破
}
}否则{
int stop_信号;
MPI\U测试(所有记录停止和停止信号,MPI\U状态忽略);
如果(停止信号)
{
MPI_Reduce(&found,NULL,1,MPI_INT,MPI_SUM,root,MPI_COMM_WORLD);
printf(“秩%d在接收到信号后停止。\n”,秩);
打破
}
}
};
MPI_Finalize();
}
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
const int iter_max = 10000;
const int difficulty = 20000;
int find_stuff()
{
int num_iters = rand() % iter_max;
for (int i = 0; i < num_iters; i++) {
if (rand() % difficulty == 0) {
return 1;
}
}
return 0;
}
const int stop_tag = 42;
const int root = 0;
int forward_stop(MPI_Request* root_recv_stop, MPI_Request* all_recv_stop, int found_count)
{
int flag;
MPI_Status status;
if (found_count == 0) {
MPI_Test(root_recv_stop, &flag, &status);
} else {
// If we find something on the root, we actually wait until we receive our own message.
MPI_Wait(root_recv_stop, &status);
flag = 1;
}
if (flag) {
printf("Forwarding stop signal from %d\n", status.MPI_SOURCE);
MPI_Ibarrier(MPI_COMM_WORLD, all_recv_stop);
MPI_Wait(all_recv_stop, MPI_STATUS_IGNORE);
// We must post some additional receives if multiple ranks found something at the same time
MPI_Reduce(MPI_IN_PLACE, &found_count, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD);
for (found_count--; found_count > 0; found_count--) {
MPI_Recv(NULL, 0, MPI_CHAR, MPI_ANY_SOURCE, stop_tag, MPI_COMM_WORLD, &status);
printf("Additional stop from: %d\n", status.MPI_SOURCE);
}
return 1;
}
return 0;
}
int main()
{
MPI_Init(NULL, NULL);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
srand(rank);
MPI_Request root_recv_stop;
MPI_Request all_recv_stop;
if (rank == root) {
MPI_Irecv(NULL, 0, MPI_CHAR, MPI_ANY_SOURCE, stop_tag, MPI_COMM_WORLD, &root_recv_stop);
} else {
// You may want to use an extra communicator here, to avoid messing with other barriers
MPI_Ibarrier(MPI_COMM_WORLD, &all_recv_stop);
}
while (1) {
int found = find_stuff();
if (found) {
printf("Rank %d found something.\n", rank);
// Note: We cannot post this as blocking, otherwise there is a deadlock with the reduce
MPI_Request req;
MPI_Isend(NULL, 0, MPI_CHAR, root, stop_tag, MPI_COMM_WORLD, &req);
if (rank != root) {
// We know that we are going to receive our own stop signal.
// This avoids running another useless iteration
MPI_Wait(&all_recv_stop, MPI_STATUS_IGNORE);
MPI_Reduce(&found, NULL, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD);
MPI_Wait(&req, MPI_STATUS_IGNORE);
break;
}
MPI_Wait(&req, MPI_STATUS_IGNORE);
}
if (rank == root) {
if (forward_stop(&root_recv_stop, &all_recv_stop, found)) {
break;
}
} else {
int stop_signal;
MPI_Test(&all_recv_stop, &stop_signal, MPI_STATUS_IGNORE);
if (stop_signal)
{
MPI_Reduce(&found, NULL, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD);
printf("Rank %d stopping after receiving signal.\n", rank);
break;
}
}
};
MPI_Finalize();
}