OpenMPI: Fehlermeldung bei MPI_Finalize



  • Hallo alle zusammen.

    Ich hoffe erstmal ich schreibe in das richtige Forum.
    Ich habe ein Programm beschrieben, was eine lange numerische Rechnung durchführt und benutze den Solver Mumps für lineare Gleichungssysteme, der sich auch parallelisieren lässt. Daher habe ich mir das notwendigste über MPI angeeignet, aber bin ein blutiger Anfänger.

    Es läuft eigentlich alles ganz gut, nur beim beenden des Programms kommt eine Fehlermeldung:

    3 says goodbye
    *** The MPI_Finalize() function was called after MPI_FINALIZE was invoked.
    *** This is disallowed by the MPI standard.
    *** Your MPI job will now abort.
    [uranos:24002] Abort after MPI_FINALIZE completed successfully; not able to guarantee that all other processes were killed!
    1 says goodbye
    *** The MPI_Finalize() function was called after MPI_FINALIZE was invoked.
    *** This is disallowed by the MPI standard.
    *** Your MPI job will now abort.
    [uranos:24000] Abort after MPI_FINALIZE completed successfully; not able to guarantee that all other processes were killed!
    0 says goodbye
    *** The MPI_Finalize() function was called after MPI_FINALIZE was invoked.
    *** This is disallowed by the MPI standard.
    *** Your MPI job will now abort.
    [uranos:23999] Abort after MPI_FINALIZE completed successfully; not able to guarantee that all other processes were killed!
    2 says goodbye
    *** The MPI_Finalize() function was called after MPI_FINALIZE was invoked.
    *** This is disallowed by the MPI standard.
    *** Your MPI job will now abort.
    [uranos:24001] Abort after MPI_FINALIZE completed successfully; not able to guarantee that all other processes were killed!
    

    Die Slave-prozesse machen eigentlich nur Folgendes:

    int main(int argc, char* argv[])
    {
      MPI_Init(&argc, &argv);
    
      mumps = new MumpsInterface(true);
    
      // Job for Slave
      if(!mumps->is_host)
        {      
          int buf;
          MPI_Status status;
          bool abort = false;
          while(!abort)
    	{
    	  MPI_Status status;
    	  int buf;
    
    	  MPI_Recv(&buf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);      
    	  switch(buf)
    	    {
    	    case 1:
    	      mumps->help_analyze();
    	      mumps->help_factorize();	  
    	      break;
    	    case 2:
    	      mumps->help_solve();
    	      break;
    	    case 3:
    	      abort = true;
    	      break;	      
    	    }
    	}
          }
        else
          {
    
        // [1]
          }
        delete mumps;  
        cout << mumps->rank << " says goodbye\n";
        MPI_Finalize();
    
        return 0;
      }
    

    MumpsInterface ist eine Klasse, in der direkt der Solver angesteuert wird. Eigentlich an der Stelle nicht von Bedeutung.

    Der Master-Prozess macht folgendes:
    Dort wo [1] steht kommt eine lange Berechnung und zwischendrin mal ein

    int msg = 2;
          for(int m=1; m<mumps->size; ++m)
    	MPI_Send(&msg, 1, MPI_INT, m, 1, MPI_COMM_WORLD);	      
    
          mumps->solve(&(x[0]));
          mumps->print_result();
    

    oder ein

    int msg = 1;
      for(int m=1; m<mumps->size; ++m)
        MPI_Send(&msg, 1, MPI_INT, m, 1, MPI_COMM_WORLD);	      
    
      mumps->analyze(N_Eqn, current_entry, Rows, Cols, Entries);
      mumps->factorize();
    

    und noch weitere sequentielle Berechnungen. Beendet wird das Ganze dann mit

    int msg = 3;
      for(int m=1; m<mumps->size; ++m)
        MPI_Send(&msg, 1, MPI_INT, m, 1, MPI_COMM_WORLD);	      
    
      delete mumps;  
      cout << mumps->rank << " says goodbye\n";
      MPI_Finalize();  
    
      return 0;
    }
    

    Eigentlich funktioniert auch alles, aber diese Fehlermeldung nervt mich.
    Wenn dann würd ich es schon richtig machen.

    Kann mit der Fehlermeldung jemand etwas anfangen und erkennt, was ich falsch gemacht habe? Ich habe schon so viel versucht (MPI_Finalize einfach weglassen, nur im Host ausführen, erst Finalize bei Slave, dann bei Host, oder andersrum).
    Hat alles nichts gebracht.

    Vielen Dank schonmal.

    Edit: Sorry wegen der schlechten Code-Einrückung. Das Forum will es Emacs nicht gleich tun ;).



  • Prinzipiell müssen alle Prozesse MPI_Finalize aufrufen, und zwar als letztes nach alles anderen MPI-Funktionen. Dein Code sieht auf den ersten Blick nicht falsch aus.



  • Mal wild geraten: Rufen Methoden von MumpsInterface MPI_Finalize() auf? Ich denke da vor allem an den Destruktor.



  • Ich würde auch sagen, das sieht schwer danach aus als ob MPI_Finalize schon mal vorher aufgerufen wird an einer Stelle, die wir hier nicht sehen.



  • MUMPS benutzt anscheinend intern schon MPI. Du solltest dich da mal schlau machen, welche MPI-Funktionen man dann noch manuell aufrufen muss bzw darf.



  • MumpsInterface ist offenbar Teil von Boost Numeric Bindings welches wohl nicht mehr maintained wird. Ich finde da zumindest keine brauchbaren Infos zu. Sag doch mal, was du da genau verwendest.



  • Max3000 schrieb:

    delete mumps;  
        cout << mumps->rank << " says goodbye\n";
    

    Find den Fehler im rechten Bild 😉



  • Solche Fehler hast du verdient, wenn du manuell Speicher verwaltest :p



  • ub schrieb:

    Max3000 schrieb:

    delete mumps;  
        cout << mumps->rank << " says goodbye\n";
    

    Find den Fehler im rechten Bild 😉

    Arg, warum hab ich das nicht gesehen?



  • Hallo nochmal.

    Sorry dass ich erst so spät antworte.
    Seldon hat voll ins Schwarze getroffen:

    MumpMumpsInterface::~MumpsInterface()
    {
      // Destroy MUMPS Instance
      id.job = -2;
      dmumps_c(&id);
      MPI_Finalize();
    }
    

    Da steckt schon Finalize drin. Wenn ich die Zeile lösche funktioniert es. Wie peinlich, dass ich das nicht selbst mitbekommen habe 🙄 . MumpsInterface ist übrigens nicht das aus boost sondern eine eigene Implementierung.

    Jetzt kommt allerdings ein andere Fehler:

    *** glibc detected *** optpde: munmap_chunk(): invalid pointer: 0x00007fb7db81d988 ***
    *** glibc detected *** optpde: munmap_chunk(): invalid pointer: 0x00007f80cf52a988 ***
    [uranos:00612] *** Process received signal ***
    [uranos:00612] Signal: Aborted (6)
    [uranos:00612] Signal code:  (-6)
    ======= Backtrace: =========
    /lib/libc.so.6(+0x71e16)[0x7fb7d79b3e16]
    ...
    

    Vom Code her kann ich nicht erkennen, was da das Problem ist.
    Sequentiell läuft das Programm ohne Fehler durch.
    Ich versuch vielleicht mal mit Valgrind Speicherprobleme herauszufinden, habe mich aber mit dem Tool noch nie beschäftigt. Ich melde mich sobald ich mehr weiß.

    Vielen Dank für eure Hinweise.



  • ub schrieb:

    Max3000 schrieb:

    delete mumps;  
        cout << mumps->rank << " says goodbye\n";
    

    Find den Fehler im rechten Bild 😉

    Herrgott bin ich doof.
    Sorry, ich wusste erst nicht was du meintest.
    Jetzt ist alles klar 🙂 .
    Danke. Jetzt funktioniert alles.
    Das war wahrscheinlich das Zeichen dass ich mal eine Pause mit der Programmiererei machen sollte.

    Vielen vielen Dank euch.


  • Mod

    Max3000 schrieb:

    Danke. Jetzt funktioniert alles.

    Ich hoffe, du hast als Botschaft jetzt nicht mitgenommen, das delete eine Zeile höher zu setzen. Denn der wahre Ratschlag ist:

    Nexus schrieb:

    Solche Fehler hast du verdient, wenn du manuell Speicher verwaltest :p

    Es gibt nirgendwo einen Grund, nicht mindestens einen Smartpointer zu benutzen. Hier geht es sogar noch weiter, da das Objekt ohnehin nur Scopelebensdauer hat. Das heißt, die ganze umständliche Speicherverwaltung war von vornherein unnötig und ein automatisches Objekt würde hervorragend funktionieren! So wie fast immer, weswegen das ja auch das normale Vorgehen in C++ ist.



  • [quote="SeppJ"]

    Max3000 schrieb:

    Es gibt nirgendwo einen Grund, nicht mindestens einen Smartpointer zu benutzen. Hier geht es sogar noch weiter, da das Objekt ohnehin nur Scopelebensdauer hat. Das heißt, die ganze umständliche Speicherverwaltung war von vornherein unnötig und ein automatisches Objekt würde hervorragend funktionieren! So wie fast immer, weswegen das ja auch das normale Vorgehen in C++ ist.

    Da hast du natürlich recht.
    Ich nutze jetzt mumps als normales Objekt, nicht als Pointer und wenn ich den Scope verlasse wird sowieso alles aufgeräumt. Mit Referenzen kann ich das Objekt dann auch an andere Funktionen übergeben. Das ist dann wirklich die schönere Lösung.

    Danke für den Hinweis.


Anmelden zum Antworten