最近,我在研究中一直在开发一些异步算法。我正在做一些并行的性能研究,并且一直怀疑我没有正确理解有关各种非阻塞MPI函数的一些细节。
我在这里看到了一些有见地的帖子,
对于使用非阻塞功能,我不确定或只是想澄清一些事情,我认为这可以帮助我潜在地提高当前软件的性能。
来自MPI 3.0标准的无阻塞通信部分:
无阻塞发送启动呼叫发起 发送操作,但没有完成。在将消息复制到发送缓冲区之前,可以返回发送开始调用。需要单独的发送完成呼叫以完成通信,即,验证数据已从发送缓冲区中复制出来。 使用适当的硬件,可能会继续从发送者的内存中传输数据 在发送开始之后和发送完成之前,在发送方进行的计算同时进行。
...
如果发送模式为标准,则发送完成呼叫可以 如果消息是匹配的,则在发布匹配的接收之前返回 缓冲的。另一方面,接收完成的可能未完成 直到发布匹配的接收,并将邮件复制到 接收缓冲区。
作为关于MPI_Isend
(和类似的MPI_Irecv
)的第一组问题,似乎要确保无阻塞的发送完成,我需要使用某种机制来检查是否完整,因为在最坏的情况下,可能没有 合适的硬件来同时传输数据,对吧?因此,如果在非阻塞发送之后我从未使用过MPI_Test
或MPI_Wait
之类的东西,那么MPI_Isend
可能永远不会真正发出它的消息,对吧?
这个问题适用于我的一些工作,因为我正在通过MPI_Isend
发送消息,并且在我收到预期的响应消息之前并没有进行完整性测试,因为我想避免MPI_Test
调用的开销。虽然这种方法一直有效,但根据我的阅读看来还是有问题的。
此外,第二段似乎表明,对于标准非阻塞发送MPI_Isend
,它可能不会甚至开始发送其任何数据,直到目标进程已调用匹配的接收。给定MPI_Probe
/ MPI_Iprobe
的可用性,这是否意味着MPI_Isend
调用将至少 发送出消息的一些初步元数据,例如大小,来源和标签,以便目标进程上的探测功能可以知道要在此处发送消息,因此目标进程实际上可以过帐相应的接收?
有关是有关该探针的问题。在 Probe and Cancel 部分中,标准指出
MPI_IPROBE(source, tag, comm, flag, status)
返回flag = true
,如果有一条消息可以接收并且与参数source
,tag
和{{1} }。该调用与在程序中同一点执行的对comm
的调用所接收的消息相同,并且在状态中返回与MPI_RECV(..., source, tag, comm, status)
返回的值相同的值。否则,该呼叫将返回MPI_RECV()
,并使flag = false
不确定。
通过以上讨论,很明显,探测将告诉您是否存在与指定的status
,source
和tag
相对应的可用消息。我的问题是,您是否应该假设尚未成功传输来自成功探测的相应发送的数据?
在我看来,在阅读了标准之后,探查器知道的消息确实不一定是本地进程实际上已完全接收到的消息。鉴于先前有关标准非阻塞发送的详细信息,似乎您需要在进行探测后发布接收以确保源非阻塞标准发送将完成,因为有时源可能会发送大消息MPI不想复制到某个内部缓冲区,对吗?无论哪种方式,似乎都是在探测之后发布接收信息,这是确保您实际上从要发送的相应发送中获取完整数据的方式。这是正确的吗?
后一个问题与我的代码中的一个实例有关,在该实例中,我正在执行comm
调用,如果成功,我将执行MPI_Iprobe
调用以获取消息。但是,我认为这现在可能有问题,因为我在想,如果调查成功,则意味着它已经获得了全部信息。这对我意味着MPI_Recv
会很快运行,因为完整的消息已经在本地内存中的某个位置。但是,我认为这是一个错误的假设,因为对此进行一些澄清将是有帮助的。
答案 0 :(得分:2)
MPI标准不强制要求进度线程。这意味着#### Step 5: Posterior predictive checks
y_draw <- data.frame(extract(mod, pars = "y_draw"))
And plot the mean, lower HPDI and upper HPDI draws of these draws against the actual data.
df$drawMean <- apply(y_draw, 2, mean)
df$HPDI_Low <- apply(y_draw, 2, function(i) HPDIFunct(i)[[2]][1])
df$HPDI_Hi <- apply(y_draw, 2, function(i) HPDIFunct(i)[[3]][1])
### Step 6: plot posterior draws against actual data
ggplot(df, aes(x = factor(bevType), colour = factor(group))) +
geom_jitter(aes(y = score), shape = 1, position = position_dodge(width=0.9)) +
geom_point(aes(y = drawMean), position = position_dodge(width=0.9), stat = "summary", fun.y = "mean", shape = 3, size = 3, stroke = 2) +
geom_point(aes(y = HPDI_Low), position = position_dodge(width=0.9), stat = "summary", fun.y = "mean", shape = 1, size = 3, stroke = 1) +
geom_point(aes(y = HPDI_Hi), position = position_dodge(width=0.9), stat = "summary", fun.y = "mean", shape = 1, size = 3, stroke = 1) +
scale_colour_manual(name = "Experimental Group", labels = c("Group 1", "Group 2", "Group 3"), values = c("#616a6b", "#00AFBB", "#E7B800")) +
scale_x_discrete(labels = c("Water", "Decaf", "Coffee")) +
labs(x = "Beverage Type", y = "Expectancy of Withdrawal Alleviation") +
scale_y_continuous(breaks = seq(0,10,2)) +
theme(axis.text.x = element_text(size = 12),
axis.title.x = element_text(face = "bold"),
axis.title.y = element_text(face = "bold"),
axis.text.y = element_text(size = 12),
legend.title = element_text(size = 13, face = "bold"))
可能在通信继续进行之前什么都不做。大多数MPI子例程都是在后台进行的,最明显的是MPI_Isend()
,MPI_Test()
和MPI_Wait()
。
恐怕您正在混合进度和同步发送(例如MPI_Probe()
)。
MPI_Ssend()
是本地操作,这意味着它将不会与发送方联系,也不会询问是否发送了某些内容或对其进行处理。
在性能方面,应该尽可能避免出现意外消息,这意味着接收消息应在消息的另一端发送之前在一端发送。
这里的性能和可移植性之间需要权衡:
请记住,大多数MPI实现(请注意,这不是MPI标准强制要求的,您不应依赖它)以急切的模式发送小消息。
这意味着MPI_Probe()
如果消息足够小(并且足够小取决于您的MPI实现,如何调整它或使用哪种互连),可能会立即返回。