2016-08-08 17 views
0

In Bezug auf MPI_Comm_create, sagt der MPI-StandardBenötigen Sie Hilfe MPI_Comm_create Verständnis

MPI_COMM_CREATE (comm, Gruppe, Newcomm)

... Die Funktion Kollektiv und muss von allen Prozessen in die Gruppe genannt werden von Komm.

nahm ich dies so, dass, zum Beispiel, wenn das comm Argument MPI_COMM_WORLD ist, dann alle Prozesse MPI_COMM_WORLD nennen müssen.

Allerdings habe ich eine Variation über einen Code im Internet geschrieben, der die Verwendung von MPI_Comm_create demonstriert. Es ist unten. Sie können sehen, dass es zwei Stellen gibt, an denen MPI_Comm_create aufgerufen wird, und nicht von allen Prozessen. Und trotzdem läuft der Code gut.

Habe ich Glück gehabt? Bin ich auf ein implementierungsabhängiges Feature gestoßen? Mißverstehe ich den MPI-Standard? Ist die Idee, dass die beiden Aufrufe dazu führen, dass alle MPI_Comm_create so "am Ende des Tages" aufrufen, ist es in Ordnung? Vielen Dank. Hier ist der Code:

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


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

    MPI_Comm even_comm, odd_comm; 
    MPI_Group even_group, odd_group, world_group; 
    int id, even_id, odd_id; 
    int *even_ranks, *odd_ranks; 
    int num_ranks, num_even_ranks, num_odd_ranks; 
    int err_mpi, i, j; 
    int even_sum, odd_sum; 


    err_mpi = MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &num_ranks); 
    MPI_Comm_rank(MPI_COMM_WORLD, &id); 

    MPI_Comm_group(MPI_COMM_WORLD, &world_group); 

    num_even_ranks = (num_ranks+1)/2; 
    even_ranks = (int *)malloc(num_even_ranks*sizeof(int)); 
    j=0; 
    for (i=0; i<num_ranks; i++){ 
     if (i%2 == 0) { 
     even_ranks[j] = i; 
     j++; 
     } 
    } 

    num_odd_ranks = num_ranks/2; 
    odd_ranks = (int *)malloc(num_odd_ranks*sizeof(int)); 
    j=0; 
    for (i=0; i<num_ranks; i++){ 
     if (i%2 == 1) { 
     odd_ranks[j] = i; 
     j++; 
     } 
    } 

    if (id%2 == 0){ 
     MPI_Group_incl(world_group, num_even_ranks, even_ranks, &even_group); 
     // RIGHT HERE, all procs are NOT calling! 
     MPI_Comm_create(MPI_COMM_WORLD, even_group, &even_comm); 
     MPI_Comm_rank(even_comm, &even_id); 
     odd_id = -1; 
    } else { 
     MPI_Group_incl(world_group, num_odd_ranks, odd_ranks, &odd_group); 
     // RIGHT HERE, all procs are NOT calling! 
     MPI_Comm_create(MPI_COMM_WORLD, odd_group, &odd_comm); 
     MPI_Comm_rank(odd_comm, &odd_id); 
     even_id = -1; 
    } 

    // Just to have something to do, we'll some up the ranks of 
    // the various procs in each communicator.  
    if (even_id != -1) MPI_Reduce(&id, &even_sum, 1, MPI_INT, MPI_SUM, 0, even_comm); 
    if (odd_id != -1) MPI_Reduce(&id, &odd_sum, 1, MPI_INT, MPI_SUM, 0, odd_comm); 

    if (odd_id == 0) printf("odd sum: %d\n", odd_sum); 
    if (even_id == 0) printf("even sum: %d\n", even_sum); 

    MPI_Finalize(); 

} 

Antwort

2

Obwohl die comm_create aus zwei verschiedenen Zeilen Code genannt wird, ist ein wichtiger Punkt, dass alle Prozesse in COMM_WORLD fordern comm_create zugleich. Die Tatsache, dass sie nicht aus derselben Codezeile stammen, ist nicht relevant - tatsächlich weiß die MPI-Bibliothek nicht einmal, woher comm_create aufgerufen wird.

Ein einfacheres Beispiel würde Barrier aus den beiden Zweigen aufrufen; Unabhängig davon, welche Zeile ausgeführt wird, führen alle Prozesse die gleiche Barriere aus, so dass der Code wie erwartet funktioniert.

Sie könnten den Code, der aufgerufen werden soll, einfach aus der gleichen Zeile umschreiben: Sie haben einfach Variablen namens "num_ranks", "mycomm", "mygroup" und "myid" und ein Array namens "ranks" und setzen sie gleich gerade oder ungerade Variablen abhängig vom Rang. Alle Prozesse könnten dann anrufen:

und wenn Sie wirklich wollten, könnten Sie diese später wieder zuweisen, z.

if (id%2 == 0) even_comm = mycomm; 
Verwandte Themen