程序使用OpenMPI成功,但使用MPICH 3.2.1时无法调用MPI_Allreduce

时间:2019-02-07 00:20:31

标签: mpi

我有一个使用OpenMPI库编译时可以正常运行的程序,但是当使用MPICH 3.2.1编译时,在MPI_Allreduce()中出现错误而失败。在Linux和MacOS上都会发生这种情况。

相关代码是

typedef struct reduction_packet {
  double sig;               /* logev */
  double s_width;           /* starting width */
  double s_nsites;          /* starting nsites */
  double width;             // width of motif
  double nsites_dis;            // final number of sites
  double llr;               // LLR of motif
  double classic;           // true if Classic objective function
  double ID; /* Use a double so the MPI type handle is simple. */
} REDUCE_PACKET;

REDUCE_PACKET a_packet, best_packet;
...
MPI_Allreduce((void *)&a_packet, (void *)&best_packet, 1,
   reduction_packet_type, max_packets_op, MPI_COMM_WORLD);

MPI堆栈上的根本错误是

MPIR_Localcopy(100)......: memcpy arguments alias each other, dst=0x7ffeeadd2f80 src=0x7ffeeadd2fc0 len=72

我的解释是MPICH MPI告诉我变量a_packet和best_packet重叠,因为要复制的变量的长度为72个字节,但是两个变量仅偏移了64个字节。

每个缓冲区实际上是一个由8个double组成的结构,占64个字节。我可以想象可能会有一些填充来处理对齐方式,但是编译器似乎很乐​​意在堆栈上分配这两个变量而无需填充。我已经记录了a_packetbest_packet的地址,它们与来自MPIR_Localcopy()的错误消息中报告的地址匹配。

如果我将两个变量的声明更改为

REDUCE_PACKET a_packet;
char foo[2];
REDUCE_PACKET best_packet;

程序在MPICH和OpenMPI上运行时没有错误。

为什么MPICH认为此变量需要72个字节而不是64个字节?我是否在MPI / MPICH文档中缺少某些信息,可以告知我我负责这种手动填充?

1 个答案:

答案 0 :(得分:0)

如果遇到此类错误,请仔细检查作为第3个参数传递给MPI_Allreduce()的MPI_datatype的定义:

MPI_Allreduce((void *)&a_packet, (void *)&best_packet, 1,
   reduction_packet_type, max_packets_op, MPI_COMM_WORLD);

事实证明,我们已经更改了基础C数据类型REDUCE_PACKET的定义,但没有将调用更新为MPI_Type_contiguous(),而是建立了MPI_datatype,{{ 1}}。

显然,与OpenMPI相比,MPICH更加关注可能重叠的内存副本。