Какие-нибудь рекомендации для модульного тестирования, совместимые с кодом / библиотеками, использующими MPI?

13

Обычно я пишу последовательный код, а когда я делаю, я пишу модульные тесты с помощью некоторой среды тестирования в стиле xUnit (MATLAB xUnit, PyUnit / nose или среды тестирования Google C ++).

Основываясь на беглом поиске в Google, я мало что видел в том, как практикующие юнит тестируют код, использующий MPI. Есть ли лучшие практики для этого?

По сравнению со стратегиями для модульного тестирования и разработки , основанной на тестировании , я ищу ответы, касающиеся того, какое программное обеспечение мне следует использовать для среды тестирования (если таковая существует - ответ вполне может быть «свернуть свой собственный код», в котором были бы полезны примеры нестандартного кода тестирования).

Большая часть того, что я хочу проверить, - это оценка функций правой стороны и процедуры сборки якобиевых матриц для степперов, которые будут интегрировать полудискретизированные PDE. Я буду использовать PETSc, поэтому, если есть что-то специфичное для PETSc, это будет полезно в дополнение к более общим системам тестирования.

Разъяснения правки:

Примером может быть ${PETSC_DIR}/src/ts/examples/tutorials/ex2.c, где я хотел бы проверить что-то вроде RHSFunction(оценка функции правой стороны) иRHSJacobian(оценка матрицы Якоби). Я проверял бы известные значения для собранной правой части и собранной матрицы Якоби; Я могу получить эти значения аналитически для некоторых простых проблемных случаев. Эти функции являются специфичными для приложения функциями, которые не будут выполнять никакие другие функции уровня приложения, но они могут вызывать MPI, если в функции выполняется сборка вектора или матрицы (как в приведенном выше примере PETSc). Если я пишу функции, которые вычисляют только части векторов или матриц, локальные для процессора, я хотел бы проверить по возможности глобальную собранную версию, потому что, будучи новичком в параллельном программировании, для меня более интуитивно понятно думать о глобальных векторах и глобальных матрицы. Эти тесты будут выполняться на небольших проблемных размерах и небольшом количестве процессоров.

Я могу придумать несколько стратегий для этого:

  • Стратегия, которая, вероятно, не будет работать должным образом, основанная на поиске в Google, который я проделал по этой теме, заключалась бы в создании известного вывода, параллельном обнаружении относительной / абсолютной ошибки и последующем наивном сравнении. Вывод, вероятно, будет искажен - любой, кто написал программу «Hello, world» с MPI, знает почему - что ограничивает полезность проведения модульного тестирования. ( Это послужило стимулом для постановки вопроса. ) Кажется также, что существует некоторая хитрость при вызове фреймворка модульного тестирования.
  • Записать вывод в файл (например, в PETSc, используя VecViewи MatView), и сравнить с известным выводом что-то вроде ndiffили numdiff. Мне очень нравится этот метод из предыдущего опыта выполнения модульного тестирования со сравнением файлов, что он будет привередливым и потребует некоторой фильтрации. Похоже, что этот метод отлично подходит для регрессионного тестирования, потому что я мог бы заменить приведенные выше утилиты на простые diffи не беспокоиться о соответствии текстовых форматов. Я понял, что эта стратегия более или менее соответствует тому, что предлагают WolfgangBangerth и andybauer. PETSc также, похоже, использует аналогичный подход для некоторых испытаний, которые он проводит.
  • Используйте платформу модульного тестирования, соберите все на процессор с рангом MPI 0 и попросите его выполнить модульные тесты, только если ранг процессора равен 0. Я мог бы сделать что-то похожее с нормами (возможно, это даже проще), хотя компромисс в том, что любые возвращенные ошибки скажут мне, что у меня есть проблема в моих вычислениях, но не какие элементы ошибочны. Тогда мне не нужно беспокоиться о каких-либо искаженных результатах модульного тестирования; Мне нужно только беспокоиться о правильном вызове фреймворка модульного тестирования. PETSc, по-видимому, использует нормальные сравнения в своих примерных программах, когда доступны точные решения, но при этом не использует систему модульного тестирования (и не обязательно).
Джефф Оксберри
источник
Я знаком только с внутренними тестами, поэтому не могу ничего рекомендовать. При этом ни один из этих наборов тестирования не позволяет вам указать, как запускать исполняемый файл, который вы создаете? Если они это сделают, должно быть тривиально создавать тесты, которые работают для программ MPI.
Билл Барт,
Им следует. На любом скомпилированном языке это просто исполняемый файл, поэтому для его mpiexecзапуска не должно быть никаких проблем , и включите такие вызовы, как PETScInitialize/ PETScFinalizeв код установки / разрыва. (Предположительно, если бы я не использовал PETSc, я бы заменил эти вызовы аналогами MPI_Init/ MPI_Finalize, в зависимости от библиотек, которые я использую.) Среда тестирования Google является исходной версией, поэтому она компилируется вместе с кодом, который я написать тоже не было бы проблемой.
Джефф Оксберри
Ваше описание проблемы подсказывает мне, что вы заинтересованы в использовании среды модульного тестирования для запуска интеграционных / регрессионных тестов. В этом нет ничего плохого, но вы можете уточнить свой вопрос немного подробнее. Я думаю, что если бы вы спросили специалиста по модульному тестированию, как писать модульные тесты для вашего научного кода, они бы сказали вам писать модульные тесты. То есть большинство ваших тестов не содержат правильных вызовов MPI.
Арон Ахмадиа
Позвольте мне быть более конкретным. Кое-что, что я хотел бы проверить на небольшой проблеме с небольшим числом процессоров (скажем, 1-4), это то, приведет ли моя собранная матрица Якоби к истинному глобальному якобиану. Я также хотел бы проверить мою правую функцию по отношению к известной глобальной правой стороне. Каждый такой тест должен по-прежнему выполнять только одну функцию в приложении (например, в PETSc, тестирование RHSFunctionи RHSJacobianв ${PETSC_DIR}/src/ts/examples/tutorials/ex.2) в изоляции.
Джефф Оксберри,
Я не думаю, что в настоящее время существует структура, которая поможет вам делать то, что вы хотите. Нам удалось заставить себя сделать несколько вещей для нас в PyClaw (и Лисандро использовал это в mpi4py и petsc4py). Вы смотрели на рамки тестирования в mpich?
Арон Ахмадиа,

Ответы:

8

Я счастливый пользователь GoogleTest с MPI-кодом C ++ в среде сборки CMake / CTest:

  • CMake автоматически устанавливает / связывает GoogleTest с SVN!
  • добавление тестов является одной строкой!
  • писать тесты легко! (и гугл макет очень мощный!)
  • CTest может передавать параметры командной строки в ваши тесты и экспортировать данные в CDash!

Вот как это работает. Пакет юнит-тестов, требующих mpi, записывается в некоторый my_mpi_test.cppфайл, который выглядит следующим образом:

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

CMakeLists.txt, который добавляет этот тест:

add_mpi_test(my_mpi 2)  # Uses 2 MPI processes

где add_mpi_testоборачивает CMake add_testвнутри моего корня 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)

Эта последняя часть не обязательна, но позволяет легко добавлять mpi-тесты в одну строку. Затем вы можете решить, хотите ли вы жестко закодировать число процессов MPI для каждого теста или прочитать его с помощью параметра командной строки для ctest.

gnzlbg
источник
4

Существует несколько пакетов программного обеспечения с поддержкой MPI, которые используют набор инструментов CMake для тестирования. Те, о которых я могу думать вне головы, - это Trilinos, VTK и ParaView. Я думаю, что вы не хотите предполагать, что исполняемый файл должен быть запущен с помощью mpirun и / или mpiexec. CMake поддерживает указание, как правильно запускать исполняемый файл, а также различные параметры, такие как максимальное количество используемых процессов, а также пре- и пост-флаги, если это необходимо.

Возможно, вы захотите взглянуть на раздел HPC Sites на панели мониторинга ParaView, где тесты выполняются на различных суперкомпьютерах NERSC и Argonne. Там также есть большинство настроек, которые вам нужно указать, чтобы заставить их работать на этих машинах.

Для справки: на панели инструментов Trilinos представлено большое разнообразие пакетов, и для меня это впечатляет своей организацией.

Полное раскрытие: я сотрудник Kitware, а CMake - один из проектов с открытым исходным кодом, в которых участвует Kitware.

andybauer
источник
Спасибо за ответ! Я просматривал CTest и не встречал никакой документации, кроме описания, похожего на man-страницу, на веб-сайте KitWare. Можете ли вы порекомендовать какие-либо свободно доступные учебники?
Джефф Оксберри
На вики CMake есть куча информации . Там есть куча учебников по CMake, CTest и CPack. Я нахожу большинство своих ответов на эти приложения в переполнении стека .
Andybauer
andybauer - Спасибо за ответ. Вы не против редактировать свой ответ и раскрыть свою принадлежность к KitWare?
Арон Ахмадиа,
3

Мы просто добавляем наш собственный код в deal.II - по сути, мы говорим фреймворку, чтобы он выполнял тесты mpirun -np .... Ранее мы только что использовали схему тестирования на основе Makefile (скомпилируйте, скомпонуйте, выполните тест, затем сравните вывод с ранее сохраненным), и вы можете найти это здесь:

и для контекста, цели не-MPI здесь:

Мы переписываем вещи, используя CMake / CTest, с текущей разработкой здесь:

Вольфганг Бангерт
источник
Вольфганг, спасибо за ответ! PETSc, кажется, делает нечто подобное.
Джефф Оксберри,
3

Тестовый модуль Teuchos Unit в Trilinos изначально поддерживает модульные тесты, использующие MPI. Такие вещи, как управление выводом из нескольких процессов и агрегирование прохождения / отказа по всем процессам, выполняется автоматически. Взглянем:

http://trilinos.org/docs/dev/packages/teuchos/doc/html/group__Teuchos__UnitTest__grp.html

Роско А. Бартлетт
источник