实现缓冲版MPI_Get时触发errno 14报错问题求助
问题描述
尝试实现缓冲版本的MPI_Get,实现单进程仅需从另一进程获取数据时,无需执行全局fence同步操作。程序运行时抛出报错:
Read -1, expected 40, errno = 14
运行环境为OpenMPI 4.1.2,通过mpirun -n 2启动,复现代码如下:
#include <mpi.h> #include <stdlib.h> #include <stdint.h> #include <sys/mman.h> void *ptr; static MPI_Win win; void setup(size_t maxmem) { if ((ptr = mmap (NULL, maxmem, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == (void *)(intptr_t)-1) { MPI_Abort(MPI_COMM_WORLD, 1); } MPI_Win_create (ptr, maxmem, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win); } void bufferedGet(void *origin, size_t count, size_t owner_rank, size_t offset) { MPI_Win_lock (MPI_LOCK_SHARED, owner_rank, 0, win); MPI_Get (origin, count, MPI_BYTE, owner_rank, offset, count, MPI_BYTE, win); MPI_Win_unlock (owner_rank, win); } int main(int argc, char **argv) { MPI_Init(&argc, &argv); size_t size = 409600; setup(size); void *result = malloc(10); bufferedGet(result, 10, 0, 1); free(result); MPI_Win_free(&win); munmap(ptr, size); MPI_Finalize(); }
问题根因
报错里的errno=14对应系统错误码EFAULT,代表访问了非法内存地址,核心问题出在内存窗口的权限配置上:
- 调用
mmap创建窗口挂载的内存时,仅传入了PROT_WRITE写权限,没有开启读权限。MPI RMA层在目标进程侧读取窗口内存数据时,需要内存具备可读权限,无读权限的内存访问直接触发访问错误,最终抛出读失败的报错。 - 选择的
MPI_Win_lock/MPI_Win_unlock同步逻辑本身没有问题,这组API属于MPI RMA的被动目标同步模式,本身就只需要发起方和目标方参与,不需要全局fence同步,完全匹配设计目标。 - 额外说明:当前用
MAP_PRIVATE创建匿名私有映射仅做Get操作是可以正常运行的,但如果后续要支持Put/Accumulate等写操作,写时复制的私有映射会导致目标进程无法感知其他进程写入的数据,需要替换为MAP_SHARED标志。
修复方法
修改mmap调用的权限参数,新增读权限即可,修改后的mmap代码如下:
if ((ptr = mmap (NULL, maxmem, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == (void *)(intptr_t)-1) { MPI_Abort(MPI_COMM_WORLD, 1); }
修改后重新编译运行即可正常执行,不需要额外添加全局fence操作。
内容的提问来源于stack exchange,提问作者asdfldsfdfjjfddjf
相关产品推荐
相关产品推荐

