2014-07-17 11 views
6

Ich versuche, Haufen von erzeugten Prozessen in einem einzigen intracomm einzurichten. Ich muss separate Prozesse in eindeutigen Arbeitsverzeichnissen erzeugen, da diese Teilprozesse eine Reihe von Dateien ausschreiben. Nachdem alle Prozesse in der Absicht entstanden sind, sie zu einem einzigen Intra-Kommunikator zusammenzuführen. Um das auszuprobieren, habe ich ein einfaches Testprogramm eingerichtet.MPI verschmelzen mehrere Intercoms zu einem einzigen intracomm

int main(int argc, const char * argv[]) { 
    int rank, size; 

    const int num_children = 5; 
    int error_codes; 

    MPI_Init(&argc, (char ***)&argv); 

    MPI_Comm parentcomm; 
    MPI_Comm childcomm; 
    MPI_Comm intracomm; 
    MPI_Comm_get_parent(&parentcomm); 

    if (parentcomm == MPI_COMM_NULL) { 
     printf("Current Command %s\n", argv[0]); 

     for (size_t i = 0; i < num_children; i++) { 
      MPI_Comm_spawn(argv[0], MPI_ARGV_NULL, 1, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &childcomm, &error_codes); 
      MPI_Intercomm_merge(childcomm, 0, &intracomm); 
      MPI_Barrier(childcomm); 
     } 
    } else { 
     MPI_Intercomm_merge(parentcomm, 1, &intracomm); 
     MPI_Barrier(parentcomm); 
    } 

    printf("Test\n"); 

    MPI_Barrier(intracomm); 

    printf("Test2\n"); 

    MPI_Comm_rank(intracomm, &rank); 
    MPI_Comm_size(intracomm, &size); 

    printf("Rank %d of %d\n", rank + 1, size); 

    MPI_Barrier(intracomm); 
    MPI_Finalize(); 
    return 0; 
} 

Als ich das laufen bekomme ich alle 6 Prozesse aber mein IntraComm nur zwischen dem Elternteil und dem letzten Kind hervorgebracht zu sprechen. Die resultierende Ausgabe ist

Test 
Test 
Test 
Test 
Test 
Test 
Test2 
Rank 1 of 2 
Test2 
Rank 2 of 2 

Gibt es eine Möglichkeit, mehrere Kommunikatoren in einem einzigen Kommunikator zusammenzuführen? Beachten Sie auch, dass ich diese nacheinander spawne, da ich jeden Teilprozess in einem eindeutigen Arbeitsverzeichnis ausführen muss.

Antwort

4

Wenn Sie dies tun, indem Sie MPI_COMM_SPAWN mehrmals aufrufen, dann müssen Sie es sorgfältiger tun. Nachdem Sie das erste Mal SPAWN aufgerufen haben, muss der erzeugte Prozess auch an dem nächsten Anruf an SPAWN teilnehmen, andernfalls wird es aus dem Communicator ausgelassen, den Sie zusammenführen. es endet wie folgt aussehen:

Individual Spawns

Das Problem ist, dass nur zwei Prozesse in jedem MPI_INTERCOMM_MERGE teilnehmen und Sie können drei Kommunikatoren nicht fusionieren, damit Sie nie mit einem großen Kommunikator auf diese Weise enden.

Wenn Sie stattdessen jeden Prozess in der Zusammenführung teilzunehmen, wie es geht, am Ende mit einem großen Kommunikator am Ende nach oben:

Group Spawns

Natürlich können Sie nur alle Ihre persönlichen Prozesse Laichen sofort, aber es klingt, als hättest du andere Gründe dafür, das nicht zu tun.

+0

Also Sie sagen Prozess 1 Spawns 2, dann 2 Spawns 3, etc ... Ich habe versucht, 'MPI_Comm_spawn_multiple' zu ​​vermeiden, so dass ich konnte vermeiden Sie das Durcheinander, indem Sie Arrays von Befehlen, Informationen usw. einrichten, da ich letztendlich in Fortran das tun werde. – user1139069

+0

Nein, 0 Spawns 1, dann 0 & 1 Spawn 2 usw. –

5

Ich weiß, ich bin ein Jahr alt mit dieser Antwort veraltet, aber ich dachte, dass vielleicht andere Leute eine Implementierung dieses sehen wollen. Wie der ursprüngliche Befragte sagte, gibt es keine Möglichkeit, drei (oder mehr) Kommunikatoren zusammenzuführen. Sie müssen das neue Intracomm einzeln aufbauen. Hier ist der Code, den ich verwende. Diese Version löscht das ursprüngliche Intra-Comm; Sie können oder wollen nicht, dass auf Ihre Anwendung tun abhängig:

#include <mpi.h> 


// The Borg routine: given 
// (1) a (quiesced) intra-communicator with one or more members, and 
// (2) a (quiesced) inter-communicator with exactly two members, one 
//  of which is rank zero of the intra-communicator, and 
//  the other of which is an unrelated spawned rank, 
// return a new intra-communicator which is the union of both inputs. 
// 
// This is a collective operation. All ranks of the intra- 
// communicator, and the remote rank of the inter-communicator, must 
// call this routine. Ranks that are members of the intra-comm must 
// supply the proper value for the "intra" argument, and MPI_COMM_NULL 
// for the "inter" argument. The remote inter-comm rank must 
// supply MPI_COMM_NULL for the "intra" argument, and the proper value 
// for the "inter" argument. Rank zero (only) of the intra-comm must 
// supply proper values for both arguments. 
// 
// N.B. It would make a certain amount of sense to split this into 
// separate routines for the intra-communicator processes and the 
// remote inter-communicator process. The reason we don't do that is 
// that, despite the relatively few lines of code, what's going on here 
// is really pretty complicated, and requires close coordination of the 
// participating processes. Putting all the code for all the processes 
// into this one routine makes it easier to be sure everything "lines up" 
// properly. 
MPI_Comm 
assimilateComm(MPI_Comm intra, MPI_Comm inter) 
{ 
    MPI_Comm peer = MPI_COMM_NULL; 
    MPI_Comm newInterComm = MPI_COMM_NULL; 
    MPI_Comm newIntraComm = MPI_COMM_NULL; 

    // The spawned rank will be the "high" rank in the new intra-comm 
    int high = (MPI_COMM_NULL == intra) ? 1 : 0; 

    // If this is one of the (two) ranks in the inter-comm, 
    // create a new intra-comm from the inter-comm 
    if (MPI_COMM_NULL != inter) { 
     MPI_Intercomm_merge(inter, high, &peer); 
    } else { 
     peer = MPI_COMM_NULL; 
    } 

    // Create a new inter-comm between the pre-existing intra-comm 
    // (all of it, not only rank zero), and the remote (spawned) rank, 
    // using the just-created intra-comm as the peer communicator. 
    int tag = 12345; 
    if (MPI_COMM_NULL != intra) { 
     // This task is a member of the pre-existing intra-comm 
     MPI_Intercomm_create(intra, 0, peer, 1, tag, &newInterComm); 
    } 
    else { 
     // This is the remote (spawned) task 
     MPI_Intercomm_create(MPI_COMM_SELF, 0, peer, 0, tag, &newInterComm); 
    } 

    // Now convert this inter-comm into an intra-comm 
    MPI_Intercomm_merge(newInterComm, high, &newIntraComm); 


    // Clean up the intermediaries 
    if (MPI_COMM_NULL != peer) MPI_Comm_free(&peer); 
    MPI_Comm_free(&newInterComm); 

    // Delete the original intra-comm 
    if (MPI_COMM_NULL != intra) MPI_Comm_free(&intra); 

    // Return the new intra-comm 
    return newIntraComm; 
} 
Verwandte Themen