【发布时间】:2019-07-01 01:17:12
【问题描述】:
我有一个程序在使用 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 个双精度组成的结构,占 64 个字节。我可以想象可能有一些填充来处理对齐,但是编译器似乎很乐意在堆栈上分配这两个变量而没有填充。我记录了a_packet 和best_packet 的地址,它们与MPIR_Localcopy() 的错误消息中报告的地址相匹配。
如果我将两个变量的声明更改为
REDUCE_PACKET a_packet;
char foo[2];
REDUCE_PACKET best_packet;
程序在 MPICH 和 OpenMPI 上运行没有错误。
为什么 MPICH 认为这个变量需要 72 个字节而不是 64 个字节?我是否遗漏了 MPI/MPICH 文档中的某些内容,告诉我我负责这种手动填充?
【问题讨论】:
-
minimal reproducible example 需要进行更多调查。
-
同时,您可以打印
MPI_Type_get_true_extent(reduction_packet_type, ...)并比较Open MPI和MPICH的输出 -
@GillesGouaillardet 感谢建议检查 MPI_Type_get_true_extent() 是调试此问题的关键。
标签: mpi