MPI: Как обеспечить выполнение подпрограммы только на одном процессоре на узле по умолчанию? - PullRequest
0 голосов
/ 27 февраля 2020

Я использую крупномасштабный распараллеленный код, и я новичок в самом MPI.

Я пытаюсь запустить набор команд оболочки из Fortran, и, следовательно, это будет совершенно бесполезно (и приведет к моим результатам неправильно), если выполняется на более чем одном процессоре.

Наиболее важные команды, которые я нашел, это MPI_gather и MPI_reduce, но они кажутся проблемными c, потому что они пытаются получить информацию от другие процессоры и используют их на процессоре 0, но у меня нет информации, что я звоню с других процессоров.

В основном я хочу сделать что-то вроде этого:

if (MPI_node = 0 .and. MPI_process = 0) then
   (execute a code)
end if

1 Ответ

1 голос
/ 03 марта 2020

У меня недавно была такая проблема. Я решил это с помощью MPI_Comm_split для создания коммуникатора для каждого узла. Примерно так (C ++):

char node_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
int processor_hash_id;

int global_proc_id;
int global_proc_num;

int node_proc_id;
int node_proc_num;

MPI_Comm node_comm;

//Get global info
MPI_Comm_rank(MPI_COMM_WORLD, &global_proc_id);
MPI_Comm_size(MPI_COMM_WORLD, &global_proc_num);
MPI_Get_processor_name(node_name, &name_len);

//Hash the node name
processor_hash_id = get_hash_id(node_name);

//Make a new communicator for processes only on the node
// and get node info
MPI_Comm_split(MPI_COMM_WORLD, processor_hash_id, global_proc_id, &node_comm);
MPI_Comm_rank(node_comm, &node_proc_id);
MPI_Comm_size(node_comm, &node_proc_num);

//Now, if you know the name of the "root node" to execute shell commands on:
if (node_proc_id==0 && processor_hash_id == get_hash_id("name-of-root-node"))
{
    //do whatever
}

//Some hash function
int get_hash_id(const char* s)
{
    int h = 37;
    while (*s)
    {
        h = (h * 54059) ^ (s[0] * 76963);
        s++;
    }
    return h;
}

Конечно, вам нужно знать имя узла root.

Если не имеет значения, на каком узле он выполняется, тогда я бы предложил следующее:

int global_proc_id;
int global_proc_num;

//Get global info
MPI_Comm_rank(MPI_COMM_WORLD, &global_proc_id);
MPI_Comm_size(MPI_COMM_WORLD, &global_proc_num);

if (global_proc_id==0)
{
    //do whatever
}

global_proc_id==0 будет истинно только на одном узле.

...