Gibt es Empfehlungen für Unit-Testing-Frameworks, die mit Code / Bibliotheken kompatibel sind, die MPI verwenden?

13

Normalerweise schreibe ich seriellen Code, und wenn ich das tue, schreibe ich Komponententests mit einem Testframework im xUnit-Stil (MATLAB xUnit, PyUnit / nose oder Googles C ++ - Testframework).

Basierend auf einer flüchtigen Google-Suche habe ich nicht viel darüber gesehen, wie Praktiker Unit-Test-Code verwenden, der MPI verwendet. Gibt es dafür Best Practices?

Im Vergleich zu Strategien für Komponententests und testgetriebene Entwicklung suche ich nach Antworten, welche Software ich für ein Testframework verwenden sollte (falls vorhanden - die Antwort könnte durchaus "Roll your own Code" lauten, in dem Fallbeispiele für benutzerdefinierten Testcode wären hilfreich.

Das meiste, was ich testen möchte, sind Funktionsbewertungen auf der rechten Seite und Jacobi-Matrix-Assemblierungsroutinen für Zeitschrittmacher, die semi-diskretisierte PDEs integrieren. Ich werde PETSc verwenden. Wenn es also etwas PETSc-spezifisches gibt, wäre dies zusätzlich zu allgemeineren Test-Frameworks hilfreich.

Klarstellungsänderungen:

Ein Beispiel wäre in ${PETSC_DIR}/src/ts/examples/tutorials/ex2.c, wo ich sowas testen möchte RHSFunction(eine rechtsseitige Funktionsbewertung) undRHSJacobian(eine Jacobi-Matrix-Auswertung). Ich würde gegen bekannte Werte für die zusammengebaute rechte Seite und die zusammengebaute Jacobi-Matrix testen; Ich kann diese Werte für einige einfache Problemfälle analytisch ermitteln. Diese Funktionen sind anwendungsspezifische Funktionen, die keine andere Funktion auf Anwendungsebene ausführen. Sie können jedoch MPI aufrufen, wenn die Vektor- oder Matrixassemblierung innerhalb der Funktion erfolgt (wie im oben aufgeführten verknüpften PETSc-Beispiel). Wenn ich Funktionen schreibe, die nur Teile von Vektoren oder Matrizen lokal für einen Prozessor berechnen, würde ich, wenn möglich, gegen die globale, zusammengesetzte Version testen wollen, da die parallele Programmierung neu für mich ist, ist es intuitiver, an globale Vektoren und globale zu denken Matrizen. Diese Tests würden auf kleinen Problemgrößen und einer kleinen Anzahl von Prozessoren ausgeführt.

Ich kann mir ein paar Strategien vorstellen, um dies zu tun:

  • Eine Strategie, die wahrscheinlich nicht gut funktioniert, basierend auf den Google-Suchen, die ich zu diesem Thema durchgeführt habe, wäre, eine bekannte Ausgabe zu erstellen, den relativen / absoluten Fehler parallel zu finden und dann naive Vergleiche durchzuführen. Die Ausgabe wird wahrscheinlich verstümmelt sein - jeder, der ein "Hallo Welt" -Programm mit MPI geschrieben hat, weiß warum - was den Nutzen der Durchführung von Komponententests einschränkt. ( Dies war der Anstoß, die Frage zu stellen. ) Es scheint auch eine potenzielle Schwierigkeit zu geben, das Unit-Testing-Framework aufzurufen.
  • Schreiben Sie die Ausgabe in eine Datei (z. B. in PETSc mit VecViewund MatView) und vergleichen Sie sie mit bekannten Ausgaben wie ndiffoder numdiff. Mein Bauchgefühl bei dieser Methode aus früheren Erfahrungen mit Unit-Tests mit Dateivergleichen ist, dass sie heikel ist und eine gewisse Filterung erfordert. Diese Methode scheint sich jedoch hervorragend für Regressionstests zu eignen, da ich die oben genannten Dienstprogramme durch eine einfache ersetzen könnte diffund mich nicht um das Anpassen von Textformaten kümmern muss. Ich habe festgestellt, dass diese Strategie mehr oder weniger dem entspricht, was WolfgangBangerth und andybauer vorschlagen. PETSc scheint bei einigen Tests einen ähnlichen Ansatz zu verfolgen.
  • Verwenden Sie ein Unit-Test-Framework, erfassen Sie alles auf dem Prozessor mit MPI-Rang 0 und fordern Sie ihn auf, Unit-Tests nur dann auszuführen, wenn der Prozessor-Rang 0 ist. Ich könnte mit Normen etwas Ähnliches tun (dies ist wahrscheinlich sogar noch einfacher), obwohl der Kompromiss besteht ist, dass alle zurückgegebenen Fehler mich darauf hinweisen, dass ich ein Problem in meiner Berechnung habe, aber nicht, welche Elemente fehlerhaft sind. Dann brauche ich mir keine Sorgen zu machen, dass die Ausgabe von Unit-Tests verstümmelt wird. Ich muss mich nur darum kümmern, das Unit-Testing-Framework korrekt aufzurufen. PETSc scheint normgerechte Vergleiche in seinen Beispielprogrammen zu verwenden, wenn genaue Lösungen verfügbar sind, verwendet jedoch kein Unit-Testing-Framework, um diese Vergleiche durchzuführen (und sollte dies auch nicht unbedingt tun).
Geoff Oxberry
quelle
Ich kenne mich nur mit hauseigenen Testsuiten aus, daher kann ich nichts empfehlen. Können Sie in keiner dieser Testsuiten angeben, wie die von Ihnen erstellte ausführbare Datei ausgeführt werden soll? In diesem Fall sollte es trivial sein, Tests zu erstellen, die für MPI-Programme funktionieren.
Bill Barth
Sie sollten. In jeder kompilierten Sprache ist es nur eine ausführbare Datei, daher sollte es kein Problem sein, mpiexecsie auszuführen und Aufrufe wie PETScInitialize/ PETScFinalizein den Setup- / Teardown-Code aufzunehmen. (Vermutlich würde ich, wenn ich PETSc nicht verwenden würde, diese Aufrufe durch Analoga von MPI_Init/ ersetzen MPI_Finalize, je nachdem, welche Bibliotheken ich verwende.) Das Testframework von Google ist eine quellbasierte Version und wird daher zusammen mit Code I kompiliert schreiben wäre auch kein problem.
Geoff Oxberry
Ihre Beschreibung des Problems lässt darauf schließen, dass Sie ein Unit-Testing-Framework zur Durchführung von Integrations- / Regressionstests verwenden möchten. Daran ist an sich nichts auszusetzen, aber vielleicht möchten Sie Ihre Frage noch etwas näher erläutern. Ich denke, wenn Sie einen Experten für Komponententests fragen, wie er Komponententests für Ihren wissenschaftlichen Code schreibt, wird er Sie auffordern, Tests modular zu schreiben. Das heißt, die meisten Ihrer Tests enthalten keine korrekten MPI-Aufrufe.
Aron Ahmadia
Lass mich konkreter sein. Etwas, was ich an einem kleinen Problem mit einer kleinen Anzahl von Prozessoren (sagen wir 1-4) testen möchte, wäre, ob meine zusammengesetzte Jacobi-Matrix tatsächlich das richtige globale Jacobi ergibt oder nicht. Ich möchte auch meine rechte Seite gegen eine bekannte globale rechte Seite testen. Jeder dieser Tests sollte weiterhin nur eine einzige Funktion in der Anwendung (beispielsweise in PETSc, Testing RHSFunctionund RHSJacobianin ${PETSC_DIR}/src/ts/examples/tutorials/ex.2) für sich ausüben .
Geoff Oxberry
Ich glaube nicht, dass es derzeit ein Framework gibt, das Ihnen dabei hilft, das zu tun, was Sie wollen. Wir haben es geschafft, in PyClaw ein paar Dinge für uns zu tun (und Lisandro hat es in mpi4py und petsc4py verwendet). Hast du dir das Test-Framework in mpich angesehen?
Aron Ahmadia

Antworten:

8

Ich bin ein zufriedener Nutzer von GoogleTest mit einem C ++ MPI-Code in einer CMake / CTest-Build-Umgebung:

  • CMake installiert / verlinkt automatisch googletest von svn!
  • Das Hinzufügen von Tests ist ein Einzeiler!
  • Die Tests zu schreiben ist einfach! (und Google Mock ist sehr mächtig!)
  • CTest kann Befehlszeilenparameter an Ihre Tests übergeben und Daten nach CDash exportieren!

So funktioniert es. Eine Reihe von Unit-Tests, die MPI erfordern, werden in eine my_mpi_test.cppDatei geschrieben, die so aussieht:

#include <gtest/gtest.h>
#include <boost/mpi.h>

/// Most testing libraries allow to define main yourself to override initialization.
int main(int argc, char* argv[]) {
    ::testing::InitGoogleTest(&argc, argv);  /// Set gtest environment
    mpi::environment env(argc, argv);  /// Set mpi environment
    return RUN_ALL_TESTS();  /// Execute all gtest tests
}

TEST(test_batch_name, test_name) {  /// Then you can create tests as usual,
  using namespace mpi;
  communicator world;  /// and use MPI inside your tests.
  /* ... test stuff here ... */
}

Die CMakeLists.txt, die diesen Test hinzufügt, ist:

add_mpi_test(my_mpi 2)  # Uses 2 MPI processes

Wo add_mpi_testhüllt sich CMake add_testin meine root CMakeLists.txt:

function(add_mpi_test name no_mpi_proc)
  include_directories(${MY_TESTING_INCLUDES})
      # My test are all called name_test.cpp
      add_executable(${name} ${name}_test.cpp)
      add_dependencies(${name} googletest)
  # Make sure to link MPI here too:
  target_link_libraries(${name} ${MY_TESTING_LIBS})
  set(test_parameters ${MPIEXEC_NUMPROC_FLAG} ${no_mpi_proc} "./${name}")
      add_test(NAME ${name} COMMAND ${MPIEXEC} ${test_parameters})
endfunction(add_mpi_test)

Dieser letzte Teil ist nicht erforderlich, ermöglicht jedoch das einfache Hinzufügen von MPI-Tests in einer Zeile. Anschließend können Sie entscheiden, ob Sie die Anzahl der MPI-Prozesse für jeden Test fest codieren oder über einen Befehlszeilenparameter an ctest auslesen möchten.

gnzlbg
quelle
4

Es gibt mehrere MPI-fähige Softwarepakete, die CMake verwenden Tools zum Testen verwenden. Die, an die ich auf Anhieb denken kann, sind Trilinos, VTK und ParaView. Ich würde denken, dass Sie nicht davon ausgehen möchten, dass die ausführbare Datei mit mpirun und / oder mpiexec gestartet werden muss. CMake bietet Unterstützung für das Festlegen, wie die ausführbare Datei ordnungsgemäß gestartet werden soll, sowie verschiedene Optionen, z.

Möglicherweise möchten Sie sich den Abschnitt HPC-Sites des ParaView-Dashboards ansehen die Tests auf einer Vielzahl von NERSC- und Argonne-Supercomputern ausgeführt werden. Darin verborgen sind auch die meisten Einstellungen, die Sie vornehmen müssen, damit es auf diesen Computern funktioniert.

Als Referenz dient das Trilinos-Dashboard eine Vielzahl von Paketen aufgeführt, und für mich ist die Organisation ziemlich beeindruckend.

Vollständige Offenlegung: Ich bin ein Kitware-Mitarbeiter und CMake ist eines der Open Source-Projekte, an denen Kitware beteiligt ist.

andybauer
quelle
Danke für die Antwort! Ich habe mir CTest angesehen und bis auf eine manpageähnliche Beschreibung auf der KitWare-Website keine Dokumentation gefunden. Können Sie frei verfügbare Tutorials empfehlen?
Geoff Oxberry
Im CMake-Wiki gibt es eine Reihe von Informationen . Dort gibt es eine Reihe von Tutorials für CMake, CTest und CPack. Ich finde die meisten meiner Antworten auf diese Anwendungen auf Stack Overflow .
andybauer
andybauer - Danke für die Antwort. Haben Sie etwas dagegen, Ihre Antwort zu bearbeiten und Ihre Zugehörigkeit zu KitWare offenzulegen?
Aron Ahmadia
3

Wir rollen einfach unseren eigenen Code in deal.II - im Wesentlichen weisen wir das Framework an, Tests mit auszuführen mpirun -np .... Bisher haben wir nur ein Makefile-basiertes Testschema verwendet (kompilieren, verknüpfen, Test ausführen und dann die Ausgabe mit einer zuvor gespeicherten vergleichen). Dies finden Sie hier:

und für den Kontext sind die Nicht-MPI-Ziele hier:

Wir schreiben Dinge mit CMake / CTest um, mit der aktuellen Entwicklung hier:

Wolfgang Bangerth
quelle
Wolfgang, danke für die Antwort! PETSc scheint etwas Ähnliches zu tun.
Geoff Oxberry