Zwykle piszę kod seryjny, a kiedy to robię, piszę testy jednostkowe za pomocą szkieletu testowego w stylu xUnit (MATLAB xUnit, PyUnit / nose lub szkielet testowy Google C ++).
Na podstawie pobieżnej wyszukiwarki Google nie widziałem wiele na temat tego, jak praktykujący testują kod jednostkowy, który używa MPI. Czy są na to jakieś najlepsze praktyki?
W porównaniu do strategii testowania jednostkowego i programowania opartego na testach szukam odpowiedzi dotyczących oprogramowania, którego powinienem używać w środowisku testowym (jeśli takie istnieją - odpowiedzią może być „wygenerowanie własnego kodu”, w którym pomocne byłyby przykłady niestandardowego kodu testowego).
Większość tego, co chcę przetestować, to oceny funkcji po prawej stronie i procedury składania macierzy jakobianów dla steperów czasu, które będą integrować częściowo dyskretne PDE. Będę używał PETSc, więc jeśli jest coś specyficznego dla PETSc, byłoby to pomocne w uzupełnieniu bardziej ogólnych ram testowania.
Edycje wyjaśniające:
Przykładem może być ${PETSC_DIR}/src/ts/examples/tutorials/ex2.c
testowanie czegoś takiego RHSFunction
(ocena funkcji po prawej stronie) iRHSJacobian
(ocena matrycy jakobianów). Testowałbym względem znanych wartości dla złożonej prawej strony i złożonej jakobińskiej matrycy; Mogę uzyskać te wartości analitycznie dla niektórych prostych problemów. Funkcje te są funkcjami specyficznymi dla aplikacji, które nie wykonują żadnej innej funkcji na poziomie aplikacji, ale mogą wywoływać MPI, jeśli w obrębie funkcji jest wykonywany zestaw wektorów lub macierzy (jak w powyższym przykładzie połączonego PETSc). Jeśli piszę funkcje, które obliczają tylko części wektorów lub macierzy lokalnych dla procesora, chciałbym przetestować globalną, złożoną wersję, jeśli to możliwe, ponieważ będąc nowym w programowaniu równoległym, bardziej intuicyjnie jest myśleć o wektorach globalnych i globalnych matryce. Te testy byłyby przeprowadzane na małych rozmiarach problemów i małej liczbie procesorów.
Mogę wymyślić kilka strategii, aby to zrobić:
- Strategią, która prawdopodobnie nie zadziała dobrze, na podstawie wyszukiwań Google przeprowadzonych w tym temacie, byłoby zbudowanie znanego wyniku, równoległe znalezienie względnego błędu bezwzględnego, a następnie dokonanie naiwnych porównań. Dane wyjściowe prawdopodobnie będą zniekształcone - każdy, kto napisał program „Witaj, świecie” z MPI, wie dlaczego - co ogranicza użyteczność wykonywania testów jednostkowych. ( To był impuls do zadania pytania. ) Wydaje się również, że istnieje pewna potencjalna trudność w wywołaniu ram testowania jednostkowego.
- Zapisz dane wyjściowe do pliku (na przykład w PETSc, używając
VecView
iMatView
) i porównaj ze znanymi danymi wyjściowymi za pomocą czegoś takiego jakndiff
lubnumdiff
. Moje przeczucie z tą metodą z poprzednich doświadczeń przeprowadzania testów jednostkowych z porównaniami plików jest takie, że będzie wybredna i będzie wymagała trochę filtrowania. Wydaje się, że ta metoda byłaby doskonała do testowania regresji, ponieważ mogłem zastąpić powyższe narzędzia zwykłymdiff
i nie musiałem się martwić dopasowaniem formatów tekstowych. Zrozumiałem, że ta strategia jest mniej więcej tym, co sugerują WolfgangBangerth i andybauer. Wydaje się, że PETSc stosuje podobne podejście do niektórych przeprowadzanych testów. - Użyj frameworka do testów jednostkowych, zbierz wszystko na procesor z MPI rangą 0 i poproś o wykonanie testów jednostkowych tylko wtedy, gdy procesor ma rangę 0. Mógłbym zrobić coś podobnego z normami (prawdopodobnie jest to nawet łatwiejsze w ten sposób), chociaż kompromis jest to, że wszelkie zwrócone błędy powiedzą mi, że mam problem z obliczeniami, ale nie to, które elementy są błędne. Więc nie muszę się martwić, że jakieś wyniki testów jednostkowych zostaną zniekształcone; Muszę się tylko martwić o prawidłowe wywołanie frameworka testów jednostkowych. Wydaje się, że PETSc używa normalnych porównań w swoich przykładowych programach, gdy dostępne są dokładne rozwiązania, ale nie korzysta z ram testów jednostkowych podczas dokonywania tych porównań (niekoniecznie musi to robić).
źródło
mpiexec
z uruchomieniem go i dołączeniem wywołań takich jakPETScInitialize
/PETScFinalize
w kodzie setup / teardown. (Prawdopodobnie, gdybym nie korzystał z PETSc, zastąpiłbym te wywołania analogamiMPI_Init
/MPI_Finalize
, w zależności od używanych bibliotek). Struktura testowania Google jest wersją źródłową, więc kompiluję ją razem z kodem I pisanie też nie byłoby problemem.RHSFunction
iRHSJacobian
in${PETSC_DIR}/src/ts/examples/tutorials/ex.2
) w izolacji.Odpowiedzi:
Jestem szczęśliwym użytkownikiem GoogleTest z kodem MPI C ++ w środowisku kompilacji CMake / CTest:
Tak to działa. Partia testów jednostkowych wymagających MPI jest zapisywana w
my_mpi_test.cpp
pliku, który wygląda następująco:Plik CMakeLists.txt, który dodaje ten test, to:
gdzie
add_mpi_test
otacza CMake'sadd_test
wewnątrz mojego katalogu głównego CMakeLists.txt:Ta ostatnia część nie jest konieczna, ale umożliwia łatwe dodawanie testów MPI w jednym wierszu. Następnie możesz zdecydować, czy chcesz na stałe zakodować liczbę procesów MPI dla każdego testu, czy też odczytać go za pomocą parametru wiersza poleceń, aby przetestować.
źródło
Istnieje kilka pakietów oprogramowania obsługujących MPI, które używają zestawu narzędzi CMake do testowania. Te, o których mogę myśleć z góry, to Trilinos, VTK i ParaView. Sądzę, że nie chcesz zakładać, że plik wykonywalny musi zostać uruchomiony za pomocą mpirun i / lub mpiexec. CMake ma wsparcie w określaniu, jak poprawnie uruchomić plik wykonywalny wraz z różnymi opcjami, takimi jak maksymalna liczba procesów do użycia oraz flagi wstępne i końcowe, jeśli to konieczne.
Możesz zajrzeć do sekcji Witryny HPC pulpitu nawigacyjnego ParaView, w której testy są przeprowadzane na różnych superkomputerach NERSC i Argonne. Pochowano tam również większość ustawień, które należy określić, aby działało na tych komputerach.
Dla porównania, pulpit nawigacyjny Trilinos ma na liście wiele różnych pakietów i dla mnie jest dość imponujący w swojej organizacji.
Pełne ujawnienie: jestem pracownikiem Kitware, a CMake jest jednym z projektów open source, w które zaangażowany jest Kitware.
źródło
Po prostu rzucamy własnym kodem w transakcji. II - w gruncie rzeczy mówimy frameworkowi, aby wykonał testy przy użyciu
mpirun -np ...
. Wcześniej korzystaliśmy właśnie ze schematu testowego opartego na Makefile (kompiluj, łącz, wykonuj test, a następnie porównaj dane wyjściowe z wcześniej zapisanymi) i możesz to znaleźć tutaj:a dla kontekstu cele inne niż MPI są tutaj:
Piszemy rzeczy za pomocą CMake / CTest, z obecnym rozwojem tutaj:
źródło
Wiązka testowa Teuchos Unit w Trilinos natywnie obsługuje testy jednostkowe z wykorzystaniem MPI. Rzeczy takie jak kontrolowanie wyników z wielu procesów i agregowanie pass / fail wszystkich procesów odbywa się automatycznie. Spójrz:
http://trilinos.org/docs/dev/packages/teuchos/doc/html/group__Teuchos__UnitTest__grp.html
źródło