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ć).
mpiexec
z uruchomieniem go i dołączeniem wywołań takich jak PETScInitialize
/ PETScFinalize
w kodzie setup / teardown. (Prawdopodobnie, gdybym nie korzystał z PETSc, zastąpiłbym te wywołania analogami MPI_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
i RHSJacobian
in ${PETSC_DIR}/src/ts/examples/tutorials/ex.2
) w izolacji.