2015-01-15 6 views
5

Ich schreibe gerade eine Simulation mit boost :: mpi auf openMPI und alles funktioniert super. Sobald ich jedoch das System vergrößert habe und daher größere std :: Vektoren senden muss, bekomme ich Fehler.Gibt es eine Grenze für die Nachrichtengröße in MPI mit boost :: mpi?

#include <boost/mpi.hpp> 
#include <boost/mpi/environment.hpp> 
#include <boost/mpi/communicator.hpp> 
#include <boost/serialization/vector.hpp> 
#include <iostream> 
#include <vector> 
namespace mpi = boost::mpi; 

int main() { 
    mpi::environment env; 
    mpi::communicator world; 

    std::vector<char> a; 
    std::vector<char> b; 
    if (world.rank() == 0) { 
     for (size_t i = 1; i < 1E10; i *= 2) { 
      a.resize(i); 
      std::cout << "a " << a.size(); 
      world.isend(0, 0, a); 
      world.recv(0, 0, b); 
      std::cout << "\tB " << b.size() << std::endl; 
     } 
    } 
    return 0; 
} 

druckt:

Ich habe das Problem auf das folgende Problem reduziert

a 1 B 1 
a 2 B 2 
a 4 B 4 
.... 
a 16384 B 16384 
a 32768 B 32768 
a 65536 B 65536 
a 131072 B 0 
a 262144 B 0 
a 524288 B 0 
a 1048576 B 0 
a 2097152 B 0 

Ich bin mir bewusst, dass es eine Grenze zu einer Größe mpi Nachricht ist, aber 65kB scheint ein bisschen tief zu mir. Gibt es eine Möglichkeit, größere Nachrichten zu senden?

+0

Nach [diese] (http://stackoverflow.com/questions/13558861/maximale Datenmenge, die gesendet werden kann, wenn Sie -misend verwenden) Sie sollten nicht einmal in der Nähe des Maximums sein. Nachrichtengröße. Keine Ahnung, was hier schief läuft. –

+0

Was passiert, wenn Sie 'isend' in' send' ändern? Es kann sein, dass das nicht blockierende Senden ein Problem verursacht. – NathanOliver

+0

@NathanOliver: Wenn ich das zu sendende Isend ändere, stoppt es einfach (Blöcke) nach dem Schreiben der Zeile a 65536 B 65536. – tik

Antwort

3

Die Grenze der Nachrichtengröße ist die gleiche wie für MPI_Send: INT_MAX.

Das Problem ist, dass Sie nicht warten, bis die isend fertig ist, bevor Sie den Vektor a in der nächsten Iteration in der Größe ändern. Dies bedeutet, dass isend ungültige Daten aufgrund der Umverteilungen im Vektor a lesen. Beachten Sie, dass der Puffer a als Referenz an boost::mpi übergeben wird und Sie daher den Puffer a nicht ändern dürfen, bis die Operation isend beendet ist.

Wenn Sie Ihr Programm mit valgrind ausführen, werden Sie ungültig sehen liest, sobald i = 131072

Der Grund Ihr Programm bis 65536 Bytes arbeitet, ist, dass OpenMPI Nachrichten senden wird direkt, wenn sie als die kleiner sind Komponenten btl_eager_limit. Für die Komponente self (Senden an den eigenen Prozess) ist dies 128*1024 Byte. Da boost::serialization dem Bytestream die Größe std::vector hinzufügt, überschreiten Sie diese eager_limit, sobald Sie 128*1024 = 131072 als Eingabegröße verwenden.

Code zu beheben, den boost::mpi::request Rückgabewert von isend() speichern und dann wait() der Schleife bis zum Ende hinzufügen:

#include <boost/mpi.hpp> 
#include <boost/mpi/environment.hpp> 
#include <boost/mpi/communicator.hpp> 
#include <boost/serialization/vector.hpp> 
#include <iostream> 
#include <vector> 
namespace mpi = boost::mpi; 

int main() { 
    mpi::environment env; 
    mpi::communicator world; 

    std::vector<char> a; 
    std::vector<char> b; 
    if (world.rank() == 0) { 
     for (size_t i = 1; i < 1E9; i *= 2) { 
      a.resize(i); 
      std::cout << "a " << a.size(); 
      mpi::request req = world.isend(0, 0, a); 
      world.recv(0, 0, b); 
      std::cout << "\tB " << b.size() << std::endl; 
      req.wait(); 
     } 
    } 
    return 0; 
}