- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个应用程序,其中每个处理器使用 MPI_Isend
向其他一些处理器发送一堆消息,然后接收一些未知数量的消息。
在我的小示例程序(下面的代码)中,我有 4 个处理器向其余 3 个处理器中的每一个发送 4 条消息,因此每个处理器应该接收 12 条消息。
我看到的问题是当我的机器运行正常时,我的程序输出如下
Rank 2 receives 12 msgs; Global count = 48
Rank 1 receives 12 msgs; Global count = 48
Rank 3 receives 12 msgs; Global count = 48
Rank 0 receives 12 msgs; Global count = 48
但有时,一些处理器没有收到足够的消息:
Rank 1 receives 9 msgs; Global count = 37
Rank 3 receives 12 msgs; Global count = 37
Rank 2 receives 4 msgs; Global count = 37
Rank 0 receives 12 msgs; Global count = 37
我知道问题可能出在 while-loop
上,我在其中使用 MPI_Iprobe
检查传入消息并在检查返回 false 时立即退出循环。但我不知道如何以不同的方式做到这一点。换句话说,我如何确保所有处理器在到达 MPI_Allreduce
语句时收到它们应该收到的所有消息?
我的程序是这样的:
#include "mpi.h"
#include <stdbool.h>
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
int rank, p;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
//ASSUMPTION: using 4 procs
//Don't worry about this part.
//just some stupid way to determine the receivers.
// Irrelevant to the question.
int recvs[3];
int i = 0, nei = 0;
for (; nei < 4; ++nei)
{
if (nei != rank)
{
recvs[i] = nei;
++i;
}
}
//Proc sending msgs to its neighbors.
//In this case, it's all other procs. (but in my real app, it's almost never the case)
int TAG = 0;
int buff[4] = {555, 666, 777, 888};
int local_counts[4] = {0, 0, 0, 0}; //EDIT 1
for (nei = 0; nei < 3; ++nei)
{
for (i = 0; i < 4; ++i)
{
MPI_Request req;
MPI_Isend(&buff[i], 1, MPI_INT, recvs[nei], TAG, MPI_COMM_WORLD, &req);
local_counts[recvs[nei]] += 1; //EDIT 1
}
}
//EDIT 1: tell processors how many msgs they're supposed to get
int global_counts[4];
int expectedRecvCount;
MPI_Reduce(local_counts, global_counts, 4, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Scatter(global_counts, 1, MPI_INT, &expectedRecvCount, 1, MPI_INT, 0, MPI_COMM_WORLD);
//Receiving
int recvCount = 0;
MPI_Status status;
int hasMsg = 0;
int num;
do
{
MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &hasMsg, &status);
if (hasMsg)
{
MPI_Recv(&num, 1, MPI_INT, status.MPI_SOURCE, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
++recvCount;
printf("\nRank %d got %d from %d", rank, num, status.MPI_SOURCE);
}
}
while (recvCount < expectedRecvCount); //EDIT 1
//while (hasMsg);
//Total number msgs received by all procs.
//Now here's where I see the problem!!!
MPI_Allreduce(&recvCount, &global_count, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
printf("\nRank %d receives %d msgs; Global count = %d", rank, recvCount, global_count);
MPI_Finalize();
return 0;
===========================================
编辑 1
我能想到的一种方法是每个处理器跟踪它发送给其他处理器的消息数量。然后在发送操作完成后,我将对这些消息计数执行 MPI_Reduce
,然后执行 MPI_Scatter
。这样每个处理器就会知道它应该接收多少消息。 (见代码)任何人都可以评论这种方法的性能吗?它会潜在地严重影响性能吗?
最佳答案
从接收方的角度来看,我如何确保已收到使用 MPI_Isend 发送的所有消息?- MPI不提供那个功能,你只能知道所有的MPI_Isend操作已经完成。
换句话说,接收者基本上不知道发送者将发送多少消息。但是发件人知道他们什么时候没有更多的消息要发送。那么,您能否使用一条消息来通知接收者从等级 n 开始不再接收任何消息?
您的代码正在解决另一个问题,如何确保所有 MPI_Isend 操作都已完成?
这是基于您的示例的代码。我没有使用 MPI_Iprobe,因为你的 MPI_Iprobe 和 if 语句之间没有计算。相反,我使用了 MPI_Probe。
以下代码确保所有消息都已发送,并且当一个进程收到来自所有其他进程的 stopTAG
消息时,该进程将停止接收消息。
#include "mpi.h"
#include <stdbool.h>
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
//ASSUMPTION: using 4 procs
//Don't worry about this part.
//just some stupid way to determine the receivers.
// Irrelevant to the question.
int recvs[3];
int i = 0, nei = 0;
for (; nei < 4; ++nei)
{
if (nei != rank)
{
recvs[i] = nei;
++i;
}
}
//Proc sending msgs to its neighbors.
//In this case, it's all other procs. (but in my real app, it's almost never the case)
int TAG = 0;
int stopTAG = 1;
int buff[4] = {555, 666, 777, 888};
MPI_Request req[3*5];
for (nei = 0; nei < 3; ++nei)
{
for (i = 0; i < 4; ++i)
{
MPI_Isend(&buff[i], 1, MPI_INT, recvs[nei], TAG,
MPI_COMM_WORLD, &req[nei * 5 + i]);
}
}
for (nei = 0; nei < 3; ++nei) {
MPI_Isend(NULL, 0, MPI_CHAR, recvs[nei], stopTAG, MPI_COMM_WORLD,
&req[nei * 5 + 4]);
}
//Receiving
int recvCount = 0;
MPI_Status status;
int hasMsg = 0;
int num;
char stopArray[size];
for (i = 0; i < size; i++) {
stopArray[i] = 0;
}
stopArray[rank] = 1;
char stop;
int completedSends = 0;
do
{
MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
if (status.MPI_TAG == TAG)
{
MPI_Recv(&num, 1, MPI_INT, status.MPI_SOURCE, TAG,
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
++recvCount;
printf("Rank %d got %d from %d\n", rank, num,
status.MPI_SOURCE);
}
else if (status.MPI_TAG == stopTAG) {
MPI_Recv(NULL, 0, MPI_CHAR, status.MPI_SOURCE, stopTAG,
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
stopArray[status.MPI_SOURCE] = 1;
}
stop = 1;
for (i = 0; i < size; i++) {
stop &= stopArray[i];
}
if (completedSends < (3*5)) {
int indx;
MPI_Status status;
MPI_Waitany(3*5, req, &indx, &status);
completedSends++;
}
}
while (!stop && (completedSends <= 15));
//Total number msgs received by all procs.
//Now here's where I see the problem!!!
int global_count;
MPI_Allreduce(&recvCount, &global_count, 1, MPI_INT, MPI_SUM,
MPI_COMM_WORLD);
printf("\nRank %d receives %d msgs;\nGlobal count = %d\n", rank,
recvCount, global_count);
MPI_Finalize();
return 0;
}
关于c++ - 从接收方的角度来看,我如何确保已收到使用 MPI_Isend 发送的所有消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39226379/
在我的程序中的某个时刻,我正在使用 MPI_Isend 来通知某个事件的所有其他进程,但其中一些进程没有监听,这很好。我已经测试了这种情况,似乎可以正常完成。 我这样做可以吗?我是否应该保留每个 Is
我无法让 MPI_Isend 发送到随机目的地。如果我对目的地进行硬编码,它工作正常,但如果我尝试生成一个随机的目的地,它就不会。这是一些相关代码: MPI_Init(&argc,&argv)
我在执行 MPI 非阻塞发送时遇到问题,它会导致机器因段错误而崩溃。所有机器都正确接收数据,但是id为0的机器在MPI_Waitall()操作过程中崩溃了。任何人都可以确定导致问题的原因吗?谢谢! 这
关于 MPI_Isend,MPI 标准说“非阻塞发送调用表示系统可能开始从发送缓冲区复制数据。在调用非阻塞发送操作后,发送方不应访问发送缓冲区的任何部分,直到发送完成。 ” ( http://www.
例如, if (rank == 0) { MPI_Isend(&sendbuf, ..., 1, ..., &request); MPI_Wait(&request, ...); /
我正在尝试从左向右发送缓冲区(0->1、1->2 2->3 等...)。我非常确定进程正在从正确的合作伙伴发送和接收,但代码挂起或输出段错误。 #include "mpi.h" #include i
我正在研究异步通信并计划实现以下例程:每个进程都拥有一个必须与之通信的进程 vector ,按升序排列。它向所有较小的 rank 发送非阻塞接收,向所有较大的 rank 发送非阻塞发送。对于除进程 0
我使用 MPI 在 4 个节点上传递了总共 8 条消息。我注意到有两条消息的数组没有提供有意义的结果。我复制了下面代码的摘录?这些是我根据以下代码/结果提出的一些相关问题: MPI_Isend 是否也
我想将不同类型的数据从一个节点发送到另一个节点。例如,我有 2 个不同类型的数据:int 和 double。但是,在我将它们发送出去之后,即使我指定了类型,接收数据的节点也会收到错误的值。从下面的示例
我的程序的目的是计算内导体和外导体之间的静电势,方法是将其分成网格,然后再分成网格切片。每个处理器获取一个切片并在每个切片上运行计算。我使用 MPI_Isend 和 MPI_Irecv 在处理器之间发
对于MPI中的异步通信,以下哪个更好(在性能、可靠性、可读性等方面): MPI_Isend with buffer 然后 MPI_Iprobe & MPI_Recv 一旦接收器准备好,或者 带缓冲区的
我正在开发一个应用程序,其中每个处理器使用 MPI_Isend 向其他一些处理器发送一堆消息,然后接收一些未知数量的消息。 在我的小示例程序(下面的代码)中,我有 4 个处理器向其余 3 个处理器中的
我有以下带有 Microsoft MPI 的 c/c++ 代码 #include #include #include "mpi.h" int main (int argc, char *argv[
我已经阅读了所有 MPI 文档和教程以及我能找到的与此相关的 Stack Overflow 问题,但我仍然不完全理解 MPI_Wait 在“完成”MPI_Isend 时的行为方式。能简单概括一下吗?是
我创建了一个数组,我想用 MPI 发送它。第一部分运行良好(我认为?)但第二部分有问题。我想这是接收部分以及我如何分配数组?请看一下: if (myrank > 1) { //first pa
我是 MPI 编程新手!我尝试测量点对点通信带宽 介于实用的处理器之间。但是现在我遇到了段错误!我不明白为什么会这样。我也在 ubuntu 上尝试过 valgrind,但是不知道。所以也许有人可以帮助
我有以下代码 int main(int argc, char* argv[]) { int rank, size; MPI_Init (&argc, &argv); MP
我想了解 MPI 如何处理发送和接收。假设我分配一个 [12][50] 元素的缓冲区,如下所示: int **buf= malloc(12 * sizeof(int *)); for (i = 0;
简单问题:由于性能要求,我需要能够在发送数据的同时进行后续计算。所以我需要使用 MPI_Isend。 这安全吗? //qtasks[][] is a 2d array and Im sending
我正在创建一个程序,其中来自数组的信息被传递到不同的处理器。在下面的代码中,我尝试使用 for 循环反复向处理器发送信息或从处理器发送信息。当我在 5 核和 2 核上运行程序时,所有打印语句都按预期在
我是一名优秀的程序员,十分优秀!