如何指定在并行程序中的哪个节点上运行哪些进程

时间:2015-10-22 00:47:36

标签: parallel-processing mpi

我在一个16节点分区上的Intel Sandy Bridge集群上运行我的MPI程序。每个节点有两个处理器,每个处理器有8个核心。我开始用“mpirun -n 256 ./myprogram”运行。现在,我需要在每个节点上有代表性的进程报告该节点的两个处理器消耗的功率(使用RAPL)。我的问题是如何选择该过程。例如,如果保证将进程分配给节点为1-16,17-32,33-48等,那么我可以检查进程的MPI等级并决定是否应该报告功率。 numactl可以用于跨多个节点绑定大量进程吗?

2 个答案:

答案 0 :(得分:3)

如果您使用MPI 3.x实施,则可以使用MPI_Comm_split_type [1]和MPI_COMM_TYPE_SHARED作为split_type参数。这会将通信器(在您的情况下,肯定是MPI_COMM_WORLD)拆分为子通信器,这些子通信器正是您的集群的共享内存区域。然后,每个子通信器都有一个本地根,可以作为您的代表进程。

[1]第247-248页, MPI:消息传递接口标准(版本3.0或3.1)

答案 1 :(得分:2)

MPI标准未涵盖在特定节点上放置特定等级的问题(AFAIK)。但是,每个实现和/或机器可能/可能会提出此功能。例如,可以通过MPI启动器的选项(mpirunmpiexecsrunprunortrun,[添加这里是您首选的mpi启动器],...),或者通过批处理调度程序(如果适用)。因此,为了获得这些特定信息,我建议您参考MPI库文档,批处理调度程序文档或机器文档。

但是,您想要的功能独立于实际的MPI流程位置。无论进程如何放在计算节点上,您都可以非常轻松地实现它。这可以通过这种方式实现:

  1. 通过MPI_Get_processor_name()gethostname()或您认为合适的任何其他方式查询当前流程运行的节点的名称。 MPI_Get_processor_name()是MPI标准,我建议将其用于便携性原因。
  2. 通过MPI_Allgather()为每个进程收集值,以了解彼此的节点名称。
  3. 对于每个节点上运行最小排名的过程,请执行报告功率测量所需的任何操作。
  4. 这可能是这样的:

    #include <mpi.h>
    #include <iostream>
    #include <cstring>
    
    bool amIFirstOnNode() {
        int rank, size;
        MPI_Comm_rank( MPI_COMM_WORLD, &rank );
        MPI_Comm_size( MPI_COMM_WORLD, &size );
        char names[size][MPI_MAX_PROCESSOR_NAME];
        int len;
        MPI_Get_processor_name( names[rank], &len );
        MPI_Allgather( MPI_IN_PLACE, 0, 0, names[0], MPI_MAX_PROCESSOR_NAME, MPI_CHAR, MPI_COMM_WORLD );
        int lower = 0;
        while ( std::strncmp( names[rank], names[lower], MPI_MAX_PROCESSOR_NAME ) != 0 ) {
            lower++;
        }
        return lower == rank;
    }
    
    int main( int argc, char *argv[] ) {
    
        MPI_Init( &argc, &argv );
        int rank;
        MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    
        bool nodeMaster = amIFirstOnNode();
        if ( nodeMaster ) {
            std::cout << "[" << rank << "] master process on the node\n";
        }
        else {
            std::cout << "[" << rank << "] not master process on the node\n";
        }
        MPI_Finalize();
    
        return 0;
    }
    

    关于跨节点使用numactl,这是可行的,但高度依赖于您的环境。例如,要在我自己的双插槽节点环境中运行,每个插槽/ NUMA节点有一个MPI进程,我有时会使用我的这个numa_bind.sh脚本:

    #!/bin/bash
    PPN=2
    numactl --cpunodebind=$(( $PMI_ID % $PPN )) --membind=$(( $PMI_ID % $PPN )) "$@"
    

    以这种方式调用:

    mpirun -ppn 2 numa_bind.sh my_mpi_binary [my_mpi_binary options]
    

    但是,当然,这假设您的环境设置PMI_ID或等效的......