2016-03-10 2 views
2

У меня есть две OpenMPI программы, которые я начинаю как этогоOpenMPI MPMD получить размер связи

mpirun -n 4 ./prog1 : -n 2 ./prog2 

Теперь, как я могу использовать MPI_Comm_size(MPI_COMM_WORLD, &size) таким образом, что я получаю значение размера, как

prog1 size=4 
prog2 size=2. 

В настоящее время я получаю «6» в обеих программах.

ответ

3

Это выполнимо, хотя и немного громоздко, чтобы получить это. Принцип состоит в том, чтобы разделить MPI_COMM_WORLD на коммуникаторы на основе значения argv[0], которое содержит имя исполняемого файла.

Это может быть что-то вроде этого:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <mpi.h> 

int main(int argc, char *argv[]) { 

    MPI_Init(&argc, &argv); 

    int wRank, wSize; 
    MPI_Comm_rank(MPI_COMM_WORLD, &wRank); 
    MPI_Comm_size(MPI_COMM_WORLD, &wSize); 

    int myLen = strlen(argv[0]) + 1; 
    int maxLen; 
    // Gathering the maximum length of the executable' name 
    MPI_Allreduce(&myLen, &maxLen, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); 

    // Allocating memory for all of them 
    char *names = malloc(wSize * maxLen); 
    // and copying my name at its place in the array 
    strcpy(names + (wRank * maxLen), argv[0]); 

    // Now collecting all executable' names 
    MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, 
        names, maxLen, MPI_CHAR, MPI_COMM_WORLD); 

    // With that, I can sort-out who is executing the same binary as me 
    int binIdx = 0; 
    while(strcmp(argv[0], names + binIdx * maxLen) != 0) { 
     binIdx++; 
    } 
    free(names); 

    // Now, all processes with the same binIdx value are running the same binary 
    // I can split MPI_COMM_WORLD accordingly 
    MPI_Comm binComm; 
    MPI_Comm_split(MPI_COMM_WORLD, binIdx, wRank, &binComm); 

    int bRank, bSize; 
    MPI_Comm_rank(binComm, &bRank); 
    MPI_Comm_size(binComm, &bSize); 

    printf("Hello from process WORLD %d/%d running %d/%d %s binary\n", 
      wRank, wSize, bRank, bSize, argv[0]); 

    MPI_Comm_free(&binComm); 

    MPI_Finalize(); 

    return 0; 
} 

На моей машине, я собрал и запустил его следующим образом:

~> mpicc mpmd.c 
~> cp a.out b.out 
~> mpirun -n 3 ./a.out : -n 2 ./b.out 
Hello from process WORLD 0/5 running 0/3 ./a.out binary 
Hello from process WORLD 1/5 running 1/3 ./a.out binary 
Hello from process WORLD 4/5 running 1/2 ./b.out binary 
Hello from process WORLD 2/5 running 2/3 ./a.out binary 
Hello from process WORLD 3/5 running 0/2 ./b.out binary 

В идеале это может быть значительно упрощается при использовании MPI_Comm_split_type(), если соответствующий тип для сортировки по двоичным файлам. К сожалению, нет такого MPI_COMM_TYPE_, предварительно определенного в стандарте 3.1 MPI. Единственным предопределенным является MPI_COMM_TYPE_SHARED для сортировки между процессами, запущенными на одних и тех же узлах вычисления общей памяти ... Слишком плохо! Может быть, что-то рассмотреть для следующей версии стандарта?

2

Поскольку вы используете Open MPI, есть очень простой OMPI-конкретное решение:

#include <stdlib.h> 

MPI_Comm appcomm; 
int app_id = atoi(getenv("OMPI_MCA_orte_app_num")); 
MPI_Comm_split(MPI_COMM_WORLD, app_id, 0, &appcomm); 

Там будет теперь, как много различных appcomm коммуникаторов, как есть контексты приложения.