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.ctestowanie 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
VecViewiMatView) i porównaj ze znanymi danymi wyjściowymi za pomocą czegoś takiego jakndifflubnumdiff. 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łymdiffi 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ć).
mpiexecz uruchomieniem go i dołączeniem wywołań takich jak PETScInitialize/ PETScFinalizew 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.
RHSFunctioni RHSJacobianin ${PETSC_DIR}/src/ts/examples/tutorials/ex.2) w izolacji.