我有一个非常简单的代码,一个数据分解问题,其中在一个循环中,每个进程在每个循环之前和之后向队列发送两个大消息.我在SMP节点集群中运行此代码(AMD Magny核心,每个节点32个核心,每个插槽8个核心).我有一段时间我正在优化这段代码.我使用pgprof和tau进行性能分析,我认为瓶颈就是沟通.我试图将通信与我的代码中的计算重叠,但它看起来实际通信在计算结束时开始:(
我在就绪模式(MPI_Rsend_init)中使用持久通信,并且在MPI_Start_all和MPI_Wait_all之间进行大量计算.代码如下所示:
void main(int argc, char *argv[])
{
some definitions;
some initializations;
MPI_Init(&argc, &argv);
MPI_Rsend_init( channel to the rank before );
MPI_Rsend_init( channel to the rank after );
MPI_Recv_init( channel to the rank before );
MPI_Recv_init( channel to the rank after );
for (timestep=0; temstep<Time; timestep++)
{
prepare data for send;
MPI_Start_all();
do computations;
MPI_Wait_all();
do work on the received data;
}
MPI_Finalize();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,实际的数据传输直到计算完成才开始,我不明白为什么.该网络使用QDR InfiniBand互连和mvapich2.每条消息大小为23MB(总共发送46 MB消息).我试图将消息传递到eager模式,因为系统中的内存足够大.我在我的作业脚本中使用以下标志:MV2_SMP_EAGERSIZE = 46M
MV2_CPU_BINDING_LEVEL = socket
MV2_CPU_BINDING_POLICY =束
这给了我大约8%的改进,可能是因为在SMP节点内更好地放置了等级,但是仍然存在通信问题.我的问题是为什么我不能有效地将通信与计算重叠?有没有我应该使用的旗帜,我想念它?我知道有些事情是错的,但无论我做了什么都还不够.
按照SMP节点内的排名顺序,节点之间的实际消息大小也是46MB(2x23MB),并且排名处于循环中.你能帮我么?要查看其他用户使用的标志,我已经检查了/etc/mvapich2.conf但它是空的.
我还有其他方法吗?你认为单方面沟通会带来更好的表现吗?我觉得有一面我不知道的旗帜或东西.
非常感谢.
在MPI中有一些称为操作进展的东西.一旦进行了适当的测试/等待调用,该标准允许非阻塞操作仅进行到完成:
非阻塞发送启动调用启动发送操作,但不完成它.在将消息复制出发送缓冲区之前,可以返回发送开始调用.需要单独的发送完成调用来完成通信,即验证数据是否已从发送缓冲区中复制出来.利用合适的硬件,数据从发送器存储器传输可以与发送器在发送之后和完成之前在发送器处完成的计算同时进行.类似地,非阻塞接收启动调用启动接收操作,但不完成它.在将消息存储到接收缓冲区之前,可以返回该调用.需要单独的接收完成调用来完成接收操作并验证数据是否已被接收到接收缓冲区中.利用合适的硬件,数据到接收器存储器的传输可以与在发起接收之后和完成之前完成的计算同时进行.
(粗体字也在标准文字中加粗;我强调的是)
虽然本文来自关于非阻塞通信的部分(MPI-3.0的§3.7; MPI-2.2中的文本完全相同),但它也适用于持久性通信请求.
我没有使用MVAPICH2,但我能够谈谈Open MPI中的实现方式.无论何时启动非阻塞操作或启动持久通信请求,操作都会添加到待处理操作的队列中,然后以两种可能的方式之一进行:
默认行为是不启用异步进程线程,因为这样做会以某种方式增加操作的延迟.
目前无法访问MVAPICH站点,但是之前我在功能列表中看到了异步进度.可能你应该从哪里开始 - 寻找启用它的方法.
另请注意,MV2_SMP_EAGERSIZE控制共享内存协议急切消息大小并且不会影响InfiniBand协议,即它只能改善驻留在同一群集节点上的进程之间的通信.
顺便说一下,不能保证接收操作将在相邻等级中的就绪发送操作之前启动,因此它们可能无法按预期运行,因为那时的排序非常重要.