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.c
cui 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
VecView
eMatView
), e confronta l'output noto con qualcosa comendiff
onumdiff
. 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 semplicediff
, 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).
mpiexec
per eseguirlo e includere chiamate come PETScInitialize
/ PETScFinalize
nel 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.
RHSFunction
e RHSJacobian
in ${PETSC_DIR}/src/ts/examples/tutorials/ex.2
) in isolamento.