2016-08-08 3 views
0

Мне нужна помощь с коммуникаторами MPI, предметом которых я относительно новичок.Создание коммуникаторов MPI для чтения файлов

У меня есть код MPI, который будет считывать ввод из нескольких входных файлов. Каждый процесс будет считываться, по крайней мере, из одного файла, большинство из них будут прочитаны более чем из нескольких. Каждый файл будет считан.

Мне нужно создать коммуникатор для каждого файла. Скажем, например, что процессы 0, 1 и 2 читаются из файла «A.dat», процессы 2, 3 и 4 читаются из файла «B.dat», а процессы 4, 5 и 6 читаются из «C. Дат». (На практике будет еще много процессов и файлов.) Мне нужны три коммуникатора. Первый должен содержать procs 0, 1 и 2; второй 2, 3 и 4; третий 4, 5 и 6. Я довольно не понимаю, как это сделать. Кто-нибудь знает как?

ответ

1

Его можно разделить больший коммуникатор на более мелкие коммуникаторы некоторых предпочтительного размера:

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

int main(int argc, char** argv) { 
    // Initialize the MPI environment 
    MPI_Init(NULL, NULL); 

    // Get the rank and size in the MPI_COMM_WORLD communicator 
    int world_rank, world_size; 
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &world_size); 

    int color = world_rank/4; //4 process (colors) for each communicator 

    MPI_Comm row_comm; 

    /* 
    The first argument is the communicator that will be used as the basis for the new communicators. 
    The second argument determines to which new communicator each processes will belong. 
    The third argument determines the ordering (rank) within each new communicator... 
    The process which passes in the smallest value for the third argument will be rank 0, the next smallest will be rank 1, and so on. 
    The final argument returns the new communicator back to the user. 
    */ 
    MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &row_comm); 

    int row_rank, row_size; 
    MPI_Comm_rank(row_comm, &row_rank); 
    MPI_Comm_size(row_comm, &row_size); 

    printf("WORLD RANK/SIZE: %d/%d \t ROW RANK/SIZE: %d/%d\n", 
      world_rank, world_size, row_rank, row_size); 

    MPI_Comm_free(&row_comm); 

    // Finalize the MPI environment. 
    MPI_Finalize(); 
} 

Или вы можете создавать группы (более гибкий способ)

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

int main(int argc, char** argv) { 
    // Initialize the MPI environment 
    MPI_Init(NULL, NULL); 

    // Get the rank and size in the original communicator 
    int world_rank, world_size; 
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &world_size); 

    // Get the group of processes in MPI_COMM_WORLD 
    MPI_Group world_group; 
    MPI_Comm_group(MPI_COMM_WORLD, &world_group); 

    int prime_group_size = 6; 
    const int ranks[6] = {2, 3, 5, 7, 11, 13}; 

    // Construct a group containing all of the prime ranks in world_group 
    MPI_Group prime_group; 
    MPI_Group_incl(world_group, prime_group_size, ranks, &prime_group); 

    // Create a new communicator based on the group 
    MPI_Comm prime_comm; 
    MPI_Comm_create_group(MPI_COMM_WORLD, prime_group, 0, &prime_comm); 

    int prime_rank = -1, prime_size = -1; 
    // If this rank isn't in the new communicator, it will be 
    // MPI_COMM_NULL. Using MPI_COMM_NULL for MPI_Comm_rank or 
    // MPI_Comm_size is erroneous 
    if (MPI_COMM_NULL != prime_comm) { 
     MPI_Comm_rank(prime_comm, &prime_rank); 
     MPI_Comm_size(prime_comm, &prime_size); 

     printf("WORLD RANK/SIZE: %d/%d \t PRIME RANK/SIZE: %d/%d\n", 
       world_rank, world_size, prime_rank, prime_size); 

     MPI_Group_free(&prime_group); 
     MPI_Comm_free(&prime_comm); 
    } 


    MPI_Group_free(&world_group); 

    // Finalize the MPI environment. 
    MPI_Finalize(); 
} 

REFERENCE

+0

Спасибо! Второй пример - то, что мне нужно. MPI_Comm_split не будет работать для меня. Мне интересно о вызовах MPI_Group_incl и MPI_Comm_create. Нужно ли всем процессам совершать эти звонки? У меня будет несколько коммуникаторов. Могу ли я написать код, чтобы для конкретного коммуникатора только обработчики этого коммуникатора совершали вызовы для этого коммуникатора? Еще раз спасибо. –

+0

Вы можете использовать некоторую структуру, такую ​​как MAP, в сочетании с условными выражениями, чтобы сделать выбранный набор процессов выполненными вами вызовами. Что-то вроде: if (can_read_file_A [world_rank] == true) {... создать определенную группу, коммуникаторы, запустить код и освободить память ...} – Felipe