Qualche consiglio per framework di unit test compatibili con codice / librerie che usano MPI?


13

Di solito, scrivo codice seriale e, quando lo faccio, scrivo unit test con alcuni framework di test in stile xUnit (MATLAB xUnit, PyUnit / nose o il framework di test C ++ di Google).

Sulla base di una rapida ricerca su Google, non ho visto molto su come il codice unit test degli operatori che utilizza MPI. Ci sono delle migliori pratiche per questo?

Rispetto alle strategie per test unitari e sviluppo test-driven , sto cercando risposte relative a quale software dovrei usare per un framework di test (se esiste - la risposta potrebbe benissimo essere "roll your own code", in cui potrebbero essere utili esempi di codice di test personalizzato).

La maggior parte di ciò che sto cercando di testare sono le valutazioni delle funzioni sul lato destro e le routine di assemblaggio della matrice giacobina per stepper di tempo che integreranno PDE semi-discretizzate. Userò PETSc, quindi se c'è qualcosa di specifico per PETSc, ciò sarebbe utile in aggiunta a framework di test più generali.

Modifiche chiarimenti:

Un esempio potrebbe essere quello in ${PETSC_DIR}/src/ts/examples/tutorials/ex2.ccui vorrei provare qualcosa di simile RHSFunction(una valutazione della funzione sul lato destro) eRHSJacobian(una valutazione della matrice giacobina). Verificherei i valori noti per il lato destro assemblato e la matrice Jacobiana assemblata; Posso ottenere questi valori analiticamente per alcune semplici istanze problematiche. Queste funzioni sono funzioni specifiche dell'applicazione che non eserciteranno alcuna altra funzione a livello di applicazione, ma potrebbero chiamare MPI se l'assemblaggio di vettore o matrice viene eseguito all'interno della funzione (come nell'esempio PETSc collegato sopra). Se scrivo funzioni che calcolano solo porzioni di vettori o matrici locali su un processore, vorrei testare la versione globale, assemblata se possibile perché, essendo nuovo nella programmazione parallela, è più intuitivo per me pensare a vettori globali e globali matrici. Questi test verrebbero eseguiti su piccole dimensioni di problemi e un numero ridotto di processori.

Posso pensare ad alcune strategie per farlo:

  • Una strategia che probabilmente non funzionerà bene, basata sulle ricerche di Google che ho fatto su questo argomento, sarebbe quella di costruire un output noto, trovare in parallelo l'errore relativo / assoluto e quindi fare confronti ingenui. L'output sarà probabilmente confuso - chiunque abbia scritto un programma "Hello, world" con MPI sa perché - il che limita l'utilità di eseguire i test unitari. ( Questo è stato lo stimolo per porre la domanda. ) Sembra esserci anche qualche potenziale inganno nel chiamare il framework di unit test.
  • Scrivi l'output su file (in PETSc, ad esempio, usando VecViewe MatView), e confronta l'output noto con qualcosa come ndiffo numdiff. Il mio istinto con questo metodo della precedente esperienza nel test unitario con confronti di file è che sarà pignolo e richiederà un po 'di filtraggio. Questo metodo sembra essere eccellente per i test di regressione, tuttavia, perché potrei sostituire le utilità sopra con un semplice diff, e non dovrei preoccuparmi di abbinare i formati di testo. Ho capito che questa strategia è più o meno ciò che WolfgangBangerth e Andybauer stanno suggerendo. PETSc sembra anche utilizzare un approccio simile per alcuni dei test che esegue.
  • Utilizza un framework di unit test, raccogli tutto sul processore con MPI rank 0 e chiedi di eseguire unit test solo se il rank del processore è 0. Potrei fare qualcosa di simile con le norme (probabilmente è anche più facile in quel modo), anche se il compromesso è che qualsiasi errore restituito mi dirà che ho un problema nel mio calcolo, ma non quali elementi sono in errore. Quindi non ho bisogno di preoccuparmi che l'output di test dell'unità venga confuso; Devo solo preoccuparmi di chiamare correttamente il framework di unit test. PETSc sembra utilizzare confronti a livello normativo all'interno dei suoi programmi di esempio quando sono disponibili soluzioni esatte, ma non utilizza un framework di test unitari quando effettua tali confronti (né dovrebbe, necessariamente).

Conosco solo le suite di test interne, quindi non posso consigliare nulla. Detto questo, nessuna di queste suite di test consente di specificare come eseguire il file eseguibile che si crea? Se lo fanno, dovrebbe essere banale costruire test che funzionino con i programmi MPI.
Bill Barth,

Dovrebbero. In qualsiasi linguaggio compilato, è solo un eseguibile, quindi non dovrebbe essere un problema usare mpiexecper eseguirlo e includere chiamate come PETScInitialize/ PETScFinalizenel codice setup / teardown. (Presumibilmente, se non usassi PETSc, sostituirei quelle chiamate con analoghi di MPI_Init/ MPI_Finalize, a seconda delle librerie che sto usando.) Il framework di test di Google è una versione basata su sorgenti, quindi la compilo con il codice I anche scrivere non sarebbe un problema.
Geoff Oxberry,

La tua descrizione del problema mi suggerisce che sei interessato a utilizzare un framework di unit test per eseguire test di integrazione / regressione. Di per sé non c'è nulla di sbagliato, ma potresti voler chiarire un po 'di più la tua domanda. Penso che se chiedessi a un esperto di unit test come scrivere unit test per il tuo codice scientifico, ti diranno di scrivere test in modo modulare. Cioè, la maggior parte dei test non contiene chiamate MPI appropriate.
Aron Ahmadia,

Vorrei essere più concreto. Qualcosa che vorrei testare su un piccolo problema con un piccolo numero di processori (diciamo 1-4) sarebbe se la mia matrice giacobina assemblata si traduca effettivamente nel giusto giacobino globale. Vorrei anche testare la mia funzione sul lato destro rispetto a un noto lato destro globale. Ciascuno di questi test dovrebbe comunque esercitare una sola funzione nell'applicazione (ad esempio, in PETSc, test RHSFunctione RHSJacobianin ${PETSC_DIR}/src/ts/examples/tutorials/ex.2) in isolamento.
Geoff Oxberry,

Non credo che esista attualmente un framework che ti aiuterà a fare ciò che desideri. Siamo riusciti a ingannare il naso nel fare alcune cose per noi in PyClaw, (e Lisandro l'ha usato in mpi4py e petsc4py). Hai esaminato il framework di test in mpich?
Aron Ahmadia,

Risposte:


8

Sono un felice utente di GoogleTest con un codice MPI C ++ in un ambiente di build CMake / CTest:

  • CMake installa / collega automaticamente googletest da svn!
  • l'aggiunta di test è un gioco da ragazzi!
  • scrivere i test è facile! (e google mock è molto potente!)
  • CTest può passare i parametri della riga di comando ai test ed esporta i dati su CDash!

È così che funziona. Una serie di unit test che richiedono mpi sono scritti in alcuni my_mpi_test.cppfile che assomigliano a questo:

#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 ... */
}

Il CMakeLists.txt che aggiunge questo test è:

add_mpi_test(my_mpi 2)  # Uses 2 MPI processes

dove add_mpi_testavvolge CMake add_testnella mia radice 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)

Quest'ultima parte non è necessaria ma consente di aggiungere facilmente test mpi in una riga. Quindi puoi decidere se vuoi codificare il numero di processi MPI per ogni test o leggerlo tramite un parametro della riga di comando per ctest.


4

Esistono diversi pacchetti software abilitati per MPI che utilizzano il set di strumenti CMake per i test. Quelli che mi vengono in mente dalla parte superiore della mia testa sono Trilinos, VTK e ParaView. Penserei che tu non voglia supporre che l'eseguibile debba essere lanciato con mpirun e / o mpiexec. CMake ha il supporto per specificare come avviare correttamente l'eseguibile insieme a diverse opzioni come il numero massimo di processi da usare e pre e post-flag, se necessario.

Si consiglia di esaminare la sezione Siti HPC della dashboard ParaView in cui vengono eseguiti i test su una varietà di supercomputer NERSC e Argonne. Sepolti ci sono anche la maggior parte delle impostazioni che dovresti specificare per farlo funzionare su quelle macchine.

Per riferimento, la dashboard di Trilinos ha una vasta gamma di pacchetti elencati e per me è piuttosto impressionante nella sua organizzazione.

Informativa completa: sono un dipendente di Kitware e CMake è uno dei progetti open source a cui Kitware è coinvolto.


Grazie per la risposta! Ho esaminato CTest e non ho trovato alcuna documentazione a parte una descrizione simile a una pagina man sul sito Web KitWare. Puoi consigliarmi dei tutorial disponibili gratuitamente?
Geoff Oxberry,

Ci sono un sacco di informazioni sulla wiki di CMake . Ci sono un sacco di tutorial per CMake, CTest e CPack lì. Trovo la maggior parte delle mie risposte a tali applicazioni su StackTranslate.it .
Andybauer,

andybauer - Grazie per la risposta. Ti dispiace modificare la tua risposta e rivelare la tua affiliazione con KitWare?
Aron Ahmadia,

3

Inseriamo semplicemente il nostro codice. II - in sostanza, diciamo al framework di eseguire test usando mpirun -np .... In precedenza avevamo appena utilizzato uno schema di test basato su Makefile (compilare, collegare, eseguire test, quindi confrontare l'output con uno che era stato precedentemente salvato) e puoi trovarlo qui:

e per il contesto, gli obiettivi non MPI sono qui:

Stiamo riscrivendo le cose usando CMake / CTest, con l'attuale sviluppo qui:


Wolfgang, grazie per la risposta! PETSc sembra fare qualcosa di simile.
Geoff Oxberry,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.