Alguma recomendação para estruturas de teste de unidade compatíveis com código / bibliotecas que usam MPI?

13

Normalmente, escrevo código serial e, quando o faço, escrevo testes de unidade com alguma estrutura de teste no estilo xUnit (MATLAB xUnit, PyUnit / nose ou estrutura de teste C ++ do Google).

Com base em uma pesquisa superficial do Google, não tenho visto muito sobre como os profissionais praticam o código de teste de unidade que usa o MPI. Existem práticas recomendadas para isso?

Comparado às Estratégias para teste de unidade e desenvolvimento orientado a teste , estou procurando respostas relacionadas a qual software devo usar para uma estrutura de teste (se houver alguma - a resposta pode muito bem ser "rolar seu próprio código", na qual exemplos de casos de código de teste personalizado seriam úteis).

A maior parte do que estou procurando testar são avaliações de funções do lado direito e rotinas de montagem de matrizes jacobianas para escalonadores de tempo que integrarão PDEs semi-discretizados. Eu vou usar o PETSc, portanto, se houver algo específico do PETSc, isso seria útil além das estruturas de teste mais gerais.

Edições de esclarecimento:

Um exemplo seria ${PETSC_DIR}/src/ts/examples/tutorials/ex2.c, onde eu gostaria de testar algo como RHSFunction(uma avaliação da função do lado direito) eRHSJacobian(uma avaliação da matriz jacobiana). Eu estaria testando valores conhecidos para o lado direito e a matriz jacobiana montados; Eu posso obter esses valores analiticamente para algumas instâncias simples de problemas. Essas funções são funções específicas de aplicativos que não exercitarão nenhuma outra função no nível de aplicativo, mas poderiam chamar MPI se o conjunto de vetores ou matrizes for feito dentro da função (como no exemplo PETSc vinculado acima). Se eu escrever funções que calculam apenas partes de vetores ou matrizes locais em um processador, eu gostaria de testar a versão global montada, se possível, porque, sendo nova na programação paralela, é mais intuitivo pensar em vetores globais e globais. matrizes. Esses testes seriam executados em pequenos tamanhos de problemas e em pequenos números de processadores.

Eu posso pensar em algumas estratégias para fazer isso:

  • Uma estratégia que provavelmente não funcionará bem, com base nas pesquisas do Google que fiz sobre esse tópico, seria construir uma saída conhecida, encontrar o erro relativo / absoluto em paralelo e fazer comparações ingênuas. A saída provavelmente será ilegível - quem escreveu um programa "Olá, mundo" com a MPI sabe o porquê - o que limita a utilidade de fazer o teste de unidade. ( Esse foi o ímpeto para fazer a pergunta. ) Também parece haver alguma dificuldade em chamar a estrutura de teste de unidade.
  • Escreva a saída no arquivo (no PETSc, por exemplo, usando VecViewe MatView) e compare com a saída conhecida com algo como ndiffou numdiff. Meu pressentimento com esse método da experiência anterior ao fazer testes de unidade com comparações de arquivos é que ele será exigente e exigirá alguma filtragem. Esse método parece que seria excelente para testes de regressão, no entanto, porque eu poderia substituir os utilitários acima por um simples diff, e não preciso me preocupar em combinar os formatos de texto. Concluí que essa estratégia é mais ou menos o que WolfgangBangerth e andybauer estão sugerindo. O PETSc também parece usar uma abordagem semelhante para alguns dos testes realizados.
  • Use uma estrutura de teste de unidade, reúna tudo no processador com classificação MPI 0 e peça para executar testes de unidade apenas se a classificação do processador for 0. Eu poderia fazer algo semelhante com as normas (provavelmente é ainda mais fácil assim), embora a desvantagem é que quaisquer erros retornados me dizem que tenho um problema no meu cálculo, mas não quais elementos estão com erro. Então não preciso me preocupar com a saída de qualquer teste de unidade; Só preciso me preocupar em chamar a estrutura de teste da unidade corretamente. O PETSc parece usar comparações normativas em seus programas de exemplo quando soluções exatas estão disponíveis, mas não usa uma estrutura de teste de unidade ao fazer essas comparações (nem deveria, necessariamente).
Geoff Oxberry
fonte
Estou familiarizado apenas com os conjuntos de testes internos, por isso não posso recomendar nada. Dito isto, nenhum desses conjuntos de testes permite especificar como executar o executável que você cria? Se o fizerem, deve ser trivial criar testes que funcionem para programas MPI.
Bill Barth
Eles deviam. Em qualquer linguagem compilada, é apenas um executável; portanto, não deve ser um problema mpiexecpara executá-lo, e inclui chamadas como PETScInitialize/ PETScFinalizeno código de instalação / desmontagem. (Presumivelmente, se eu não estivesse usando o PETSc, substituiria essas chamadas por análogos de MPI_Init/ MPI_Finalize, dependendo das bibliotecas que estou usando.) A estrutura de teste do Google é uma versão baseada em fonte, portanto, compile-a junto com o código I escrever também não seria um problema.
precisa saber é o seguinte
Sua descrição do problema sugere que você está interessado em usar uma estrutura de teste de unidade para executar testes de integração / regressão. Não há nada de errado nisso, mas você pode esclarecer um pouco mais a sua pergunta. Acho que se você perguntasse a um especialista em testes de unidade como escrever testes de unidade para o seu código científico, eles diriam para você escrever testes de maneira modular. Ou seja, a maioria dos seus testes não teria chamadas MPI adequadas.
Aron Ahmadia 19/09/2013
Deixe-me ser mais concreto. Algo que eu gostaria de testar em um pequeno problema com um pequeno número de processadores (por exemplo, 1-4) seria se minha matriz jacobiana montada resulta ou não na jacobiana global adequada. Eu também gostaria de testar minha função do lado direito em relação a um lado global conhecido do lado direito. Cada um desses testes ainda deve exercer apenas uma função no aplicativo (por exemplo, no PETSc, testing RHSFunctione RHSJacobianin ${PETSC_DIR}/src/ts/examples/tutorials/ex.2) isoladamente.
Geoff Oxberry
Não acho que exista uma estrutura que o ajude a fazer o que deseja. Conseguimos nos convencer a fazer algumas coisas para nós no PyClaw (e Lisandro o usou no mpi4py e petsc4py). Você já viu a estrutura de teste em mpich?
Aron Ahmadia 20/09/2013

Respostas:

8

Sou um usuário feliz do GoogleTest com um código C ++ MPI em um ambiente de criação CMake / CTest:

  • O CMake instala / vincula automaticamente googletest a partir do svn!
  • adicionar testes é uma linha!
  • escrever os testes é fácil! (e o Google mock é muito poderoso!)
  • CTest pode passar parâmetros de linha de comando para seus testes e exportar dados para CDash!

É assim que funciona. Um lote de testes de unidade que requerem mpi é gravado em algum my_mpi_test.cpparquivo parecido com este:

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

O CMakeLists.txt que adiciona esse teste é:

add_mpi_test(my_mpi 2)  # Uses 2 MPI processes

onde add_mpi_testenvolve o CMake add_testdentro da minha raiz 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)

Esta última parte não é necessária, mas permite adicionar facilmente testes de mpi em uma linha. Em seguida, você pode decidir se deseja codificar o número de processos MPI para cada teste ou lê-lo por meio de um parâmetro de linha de comando para testar.

gnzlbg
fonte
4

Existem vários pacotes de software habilitados para MPI que usam o conjunto de ferramentas CMake para teste. Os que eu consigo pensar em cima da minha cabeça são Trilinos, VTK e ParaView. Eu acho que você não quer assumir que o executável precisa ser iniciado com mpirun e / ou mpiexec. O CMake tem suporte para especificar como iniciar corretamente o executável, juntamente com diferentes opções, como o número máximo de processos a serem usados ​​e pré e pós-sinalizadores, se necessário.

Você pode consultar a seção Sites HPC do painel ParaView, onde os testes são executados em vários supercomputadores NERSC e Argonne. Enterrado também há a maioria das configurações que você precisa especificar para fazê-lo funcionar nessas máquinas.

Para referência, o painel Trilinos tem uma grande variedade de pacotes listados e para mim é bastante impressionante em sua organização.

Divulgação completa: Sou funcionário da Kitware e o CMake é um dos projetos de código aberto nos quais a Kitware está envolvida.

andybauer
fonte
Obrigado pela resposta! Eu estive pesquisando no CTest e não encontrei nenhuma documentação além de uma descrição de página de manual no site do KitWare. Você pode recomendar tutoriais disponíveis gratuitamente?
precisa saber é o seguinte
Há um monte de informações no wiki do CMake . Existem vários tutoriais para CMake, CTest e CPack lá. Eu encontro a maioria das minhas respostas para esses aplicativos no Stack Overflow .
andybauer
andybauer - Obrigado pela resposta. Você se importa de editar sua resposta e divulgar sua afiliação ao KitWare?
Aron Ahmadia 19/09/2013
3

Simplesmente rolamos nosso próprio código em deal.II - em essência, dizemos à estrutura para executar testes usando mpirun -np .... Anteriormente, tínhamos usado um esquema de teste baseado em Makefile (compilar, vincular, executar teste e comparar a saída com a que havia sido salva anteriormente) e você pode encontrar isso aqui:

e, por contexto, os destinos que não são MPI estão aqui:

Estamos reescrevendo as coisas usando o CMake / CTest, com o desenvolvimento atual aqui:

Wolfgang Bangerth
fonte
Wolfgang, obrigado pela resposta! O PETSc parece fazer algo semelhante.
precisa saber é o seguinte