主辅助模型和混合MPI/OpenMP

主辅助模型和混合MPI/OpenMP,mpi,openmp,Mpi,Openmp,对于我开发的软件包,我使用主/辅方案,其中一个进程将工作分配给其他进程。分布式工作是独立的,但需要非常可变的时间来完成,并且从共享内存环境中获益匪浅。因此,现在我有一个进程/节点,因此每个MPI进程都有12个处理器和一个共享内存环境来运行OpenMP。这一切都很好,但我的“主”进程有11个空闲处理器,1个只是分配工作=(我有一些想法来解决这个问题,我正在寻找任何输入或其他想法: 在主节点上,分配一个处理器来分配工作,以及 另外11个需要实际工作。从概念上来说,这似乎是一个 显而易见的解决方案,

对于我开发的软件包,我使用主/辅方案,其中一个进程将工作分配给其他进程。分布式工作是独立的,但需要非常可变的时间来完成,并且从共享内存环境中获益匪浅。因此,现在我有一个进程/节点,因此每个MPI进程都有12个处理器和一个共享内存环境来运行OpenMP。这一切都很好,但我的“主”进程有11个空闲处理器,1个只是分配工作=(我有一些想法来解决这个问题,我正在寻找任何输入或其他想法:

  • 在主节点上,分配一个处理器来分配工作,以及 另外11个需要实际工作。从概念上来说,这似乎是一个 显而易见的解决方案,但我还没有弄清楚如何实际操作 实施这样一个计划
  • 让主节点根据需要通过非阻塞发送分发所有工作 程序启动后,立即参与完成工作。同样,这在概念上很简单,但不知道MPI是否真的支持这样的方案(我认为它不支持)。这意味着发送100条消息,等待任何单个进程接收
  • 让所有进程为所有分配的工作加载数据,并从不同的点开始。当一个进程开始一项任务时,向所有其他进程广播此任务正在进行,因此不会被另一个进程选择。这似乎是最佳选择,但我关心的是,在广播结束之前,两个进程同时选择一项任务虽然两个进程不太可能同时选择一个新任务,但这似乎是可能的

显而易见的解决方案非常容易实现。首先,创建一个类似以下内容的MPI主机文件(开放MPI格式):

然后运行以下命令:

mpiexec --hostfile hostfile.txt -n 2 -x OMP_NUM_THREADS=11 a.out : \
                                -n 3 -x OMP_NUM_THREADS=12 a.out
将发生的情况是,
a.out
的两个副本将在
node1
上启动,并将变为秩0和秩1。对于这些副本,环境变量
OMP_NUM_THREADS
将设置为11。假设秩0是主进程,并且它不执行OpenMP并行区域,
OMP_NUM_THREADS
否则,您可以通过显式调用
omp\u set\u num\u threads(1)轻松防止任何OpenMP代码使用多个线程
。秩1将是工作线程之一,它将在并行区域中使用11个线程。在其余节点上,只启动一个MPI进程,并且
OMP_NUM_threads
的值将设置为12,因此OpenMP运行时将使用所有CPU。这些进程将变为秩2、3和4。工作线程1将有点sl是的,但是你已经说过你的工作项目需要不同的时间来完成,所以我猜有某种内置的工作平衡器

您还可以为等级0创建主/辅混合。您可以:

  • 在单独的线程中运行主程序和工作程序代码。这将使主程序代码复杂化,因为此特定工作程序必须通过与其他工作程序不同的机制(例如,通过共享内存队列或其他方式)获得工作。也可以让主程序向自身发送消息,但随后需要MPI impl能够进行MPI线程多次的校正,这通常会带来其他问题,主要是性能问题
  • 将主代码与辅助代码融合,特别是当辅助代码执行某种循环时。在这种特定情况下,您可以发布工作结果的非阻塞接收,然后在辅助循环的每次迭代中使用
    MPI_Test
    ,以确定结果消息是否已到达。如果是,请运行主循环的一次迭代,即post创建新的非阻塞接收并继续工作迭代。或者使用
    MPI\u Iprobe
    代替非阻塞接收

两者都会显著增加代码的复杂性,第二个完全弄乱了主/辅代码的分离。我宁愿坚持上面显而易见的解决方案。

如果我提交给一个大型系统,如何获得节点的名称?如果有500个节点,我只要求25个,以及哪些节点将被取消由系统计划程序终止…这取决于正在使用的批处理系统。有些允许您请求特定的插槽分配。另一些允许您在环境变量中提供主机文件的名称或整个主机列表。您可以编写脚本将其转换为适当的MPI主机文件。
mpiexec --hostfile hostfile.txt -n 2 -x OMP_NUM_THREADS=11 a.out : \
                                -n 3 -x OMP_NUM_THREADS=12 a.out