WSL2下运行mpi-sppy单边MPI测试脚本遇断言错误,锁逻辑存疑
mpi-sppy单边MPI测试脚本断言错误问题分析
环境与问题概述
- 环境:Windows 11 + WSL2 Ubuntu 22.04,
mpi4py==4.0.1,MPICH Version:4.0 - 问题:运行mpi-sppy的单边MPI测试脚本时触发第49行断言错误,排查发现rank1的
win.Lock(0)似乎在等待rank0的win.Lock(1)
相关代码片段
start = time.time() if (rank == 0): buff[:] = 3. * np.ones(array_size, dtype='d') print(f"rank {rank} - {time.time()-start}: going to sleep") time.sleep(3) print(f"rank {rank} - {time.time()-start}: woke up") buff[:] = np.arange(array_size) print(f"rank {rank} - {time.time()-start}: ready for lock") win.Lock(1) print(f"rank {rank} - {time.time()-start}: locked") win.Put((buff, array_size, mpi.DOUBLE), target_rank=1) print(f"rank {rank} - {time.time()-start}: Put") win.Unlock(1) elif (rank == 1): buff = np.ones(array_size, dtype='d') print(f"rank {rank} - {time.time()-start}: going to sleep") time.sleep(1) print(f"rank {rank} - {time.time()-start}: woke up") print(f"rank {rank} - {time.time()-start}: ready for lock") win.Lock(0) print(f"rank {rank} - {time.time()-start}: locked") win.Get((buff, array_size, mpi.DOUBLE), target_rank=0) print(f"rank {rank} - {time.time()-start}: Get") win.Unlock(0)
运行日志
rank 1 - 1.0728836059570312e-05: going to sleep rank 0 - 0.00027298927307128906: going to sleep rank 1 - 1.0001559257507324: woke up rank 1 - 1.000209093093872: ready for lock rank 0 - 3.000467300415039: woke up rank 0 - 3.0005922317504883: ready for lock rank 0 - 3.000704050064087: locked rank 1 - 3.0007107257843018: locked rank 0 - 3.002230405807495: Put rank 1 - 3.002246618270874: Get
问题分析
Lock操作逻辑说明
win.Lock(target_rank)的作用是获取目标进程窗口的独占访问锁:rank0调用win.Lock(1)是锁定rank1的窗口,rank1调用win.Lock(0)是锁定rank0的窗口。这两个操作针对不同进程的窗口,本身不存在互相等待的逻辑,属于正常的MPI单边通信锁使用方式。断言错误的根本原因
从日志可见,rank1在rank0完成Put操作前就执行了Get:
- rank1sleep1秒后就进入
Lock(0)并执行Get,此时rank0还在sleep,buff仍是初始的3.0 * np.ones - rank0sleep3秒后才修改buff为
np.arange(array_size)并执行Put,但此时rank1已经完成了Get操作
脚本的断言应该是检查rank1的buff是否等于rank0最终生成的数组,由于Get早于Put执行,导致断言失败,这属于测试脚本本身的逻辑错误,没有保证数据写入(Put)在读取(Get)之前完成。
修正建议
- 调整sleep时间:让rank1的sleep时长大于3秒,确保rank0先完成
Put再执行Get - 使用MPI同步原语:在rank1执行
Get前添加MPI.Barrier(),等待rank0完成Put后再继续 - 调整锁与操作顺序:让rank0先完成
Put并释放锁,rank1再获取锁执行Get
内容的提问来源于stack exchange,提问作者user15988
相关产品推荐
相关产品推荐

