MPI中不同节点数导致不同结果的原因

计算科学 正则 mpi 测试
2021-11-28 03:46:41

我正在尝试从我的团队中开发可能被称为遗留 Fortran 代码的东西。经过测试,我发现程序(在20个进程上运行大约需要一天时间)在单个节点(20个进程)或串行(虽然需要很长时间)上运行时有效,但是如果我增加到几个节点结果显着不同,不可忽略(尽管它不会崩溃)。寻找可能导致这种情况的原因,似乎最常见的是一些共享内存的覆盖(例如打开文件而不指定仅排名 0)。这是正确的吗?还有什么可能导致似乎是节点间通信问题?对于它的价值,它只是这个库;我们使用相同的编译器在同一个集群上运行大量其他 MPI 程序,而没有这个问题。我觉得这很奇怪,因为就我而言

我的猜测是代码中存在错误;MPI 的哪些功能/常见缺陷会导致这种行为?我以前没有见过这种问题(甚至不知道它是可能的)并且想知道如何调试它,最好不要从共享集群中占用多个节点。我也想编写单元测试来防止这种事情再次发生,但我不知道如何为只出现在几个节点上的事情编写测试。如果有人可以共享/链接到表现出这种行为的最小程序,这也将特别有帮助。

这是一个我不完全理解的大型复杂代码库,但它是模块化编写的。我有兴趣尝试为其编写单元测试以查明问题(更不用说提高可维护性)。如何测试仅显示多个节点的错误?我知道pFUnit支持 MPI,看起来他们有一个模拟 MPI,你可以快速运行它以“假装”你是并行的,而不会打扰你的集群。但是,看起来我只能模拟进程数而不是节点数。我可以用 pFUnit 做到这一点吗?否则,是否有其他一些单元测试框架可以解决问题?目前有一些用FRUIT编写的测试,但这看起来像是一个用于测试 MPI 程序的相当小的框架。

编辑:我进行了更多测试以确保它不仅仅是更多的进程。事实上,改变结果的是节点的数量。我为分布在 1、2、4 个节点上的 20 个进程运行了脚本,结果都略有不同。我重新运行了几次,它们是一致的。

编辑 2:代码使用共享内存。虽然我不明白如何,但有注释标记变量,如! MPI shared memory window. 还有一小段代码使用!$omp parallel do带有一些共享变量的 openMP。但是,注释掉 openMP 指令会产生相同的行为。

1个回答

如果没有访问实际代码,任何人都无法告诉您问题出在哪里。但以下是不同进程数量的输出(合法)不同的常见原因:

  • 如果代码必须枚举要处理的对象(例如在“令人尴尬的并行”问题中,还有基于网格的计算中的自由度),那么一个常见的策略是让每个进程枚举它在本地存储的对象,从上一个进程使用的最后一个索引开始。这意味着对象的顺序取决于进程的数量,并且许多(迭代)算法将产生取决于顺序的结果,如果它们在达到某个容差时停止,而不是将迭代误差驱动为零。

  • 浮点运算不是关联的,即一般来说a+b+ca+c+b. 这意味着归约操作通常会根据您拥有的进程数产生略有不同的结果,因此计算的最终结果也可能因进程数而异。

当然,也有可能只是代码中存在错误。

要找到问题所在,您需要找到计算流程中获得不同结果的第一个位置。换句话说,不要关注最终结果,而是检查程序的中间点——比如,在第一次迭代或时间步之后。