对与使用MPI的代码/库兼容的单元测试框架有何建议?


13

通常,我编写串行代码,然后编写,并使用一些xUnit风格的测试框架(MATLAB xUnit,PyUnit / nose或Google的C ++测试框架)编写单元测试。

基于对Google的粗略搜索,关于从业人员如何对使用MPI的测试代码进行单元化的知识很少。有什么最佳实践吗?

单元测试和测试驱动的开发策略相比,我正在寻找与应该用于测试框架的软件有关的答案(如果存在的话,答案很可能是“编写自己的代码”),其中自定义测试代码的案例示例会很有帮助)。

我要测试的大部分内容都是用于右侧步进功能的评估以及用于时间步进器的Jacobian矩阵汇编例程,这些例程将集成半离散的PDE。我将使用PETSc,因此,如果有PETSc特定的内容,那么除了更通用的测试框架之外,这也将有所帮助。

澄清度编辑:

一个示例将在中${PETSC_DIR}/src/ts/examples/tutorials/ex2.c,在该示例中,我想测试类似的内容RHSFunction(右侧函数评估),然后RHSJacobian(雅可比矩阵评估)。我将针对组装好的右侧和组装好的Jacobian矩阵的已知值进行测试;对于一些简单的问题实例,我可以通过分析获得这些值。这些函数是特定于应用程序的函数,不会执行任何其他应用程序级函数,但是如果在函数内完成矢量或矩阵汇编,则可以调用MPI(如上面的链接PETSc示例中所示)。如果我编写的函数仅计算处理器局部的矢量或矩阵的部分,则我将尽可能对全局汇编版本进行测试,因为对于并行编程来说,这是我的第一次直观思考全局矢量和全局矩阵。这些测试将在较小的问题规模和少量的处理器上运行。

我可以想到一些实现此目的的策略:

  • 根据我在该主题上所做的Google搜索,一种可能效果不佳的策略是构造一个已知的输出,并行找到相对/绝对误差,然后进行幼稚的比较。输出可能会出现乱码 -任何使用MPI编写“ Hello,world”程序的人都知道原因-这限制了进行单元测试的效用。(这是提出问题的动力。在调用单元测试框架时,似乎还存在一些潜在的棘手问题。
  • 写输出到文件(PETSc中,例如,使用VecViewMatView),和比较反对的东西,如已知的输出ndiffnumdiff。我从以前通过文件比较进行单元测试的经验中得到的这种方法的直觉是,它会很挑剔,并且需要进行一些过滤。但是,此方法似乎非常适合进行回归测试,因为我可以将上述实用程序替换为plain diff,而不必担心匹配文本格式。我已经收集到该策略或多或少是WolfgangBangerth和Andybauer所建议的。PETSc似乎也使用类似的方法进行某些测试。
  • 使用单元测试框架,将所有信息收集到MPI等级为0的处理器上,并仅在处理器等级为0时要求它执行单元测试。我可以对规范做类似的事情(这种方式可能更容易),尽管需要权衡取舍就是返回的任何错误都会告诉我我的计算有问题,但是哪些元素没有错误。然后,我不必担心任何单元测试输出都会出现乱码。我只需要担心正确调用单元测试框架。当确切的解决方案可用时,PETSc似乎在其示例程序中使用基于规范的比较,但进行比较时,它不使用单元测试框架(也不必这样做)。

我只熟悉内部测试套件,因此我不推荐任何东西。话虽这么说,这些测试套件中没有一个允许您指定如何运行所创建的可执行文件吗?如果这样做的话,构建适用于MPI程序的测试应该很简单。
Bill Barth 2013年

他们应该。在任何编译语言中,它都是可执行文件,因此使用mpiexec它来运行它应该没有问题,并且在setup / teardown代码中包含PETScInitialize/ PETScFinalize之类的调用。(大概,如果我不使用PETSc,我将使用MPI_Init/的类似物替换这些调用MPI_Finalize,具体取决于我使用的库。)Google的测试框架是基于源的版本,因此将其与代码一起编译写也不会有问题。
Geoff Oxberry

您对问题的描述向我表明您对使用单元测试框架运行集成/回归测试感兴趣。这样做本身没有什么问题,但是您可能想要进一步澄清您的问题。我想,如果您问一位单元测试专家如何为您的科学代码编写单元测试,他们会告诉您以模块化的方式编写测试。也就是说,大多数测试中都没有正确的MPI调用。
Aron Ahmadia 2013年

让我更具体一点。我想用少量处理器(例如1-4)测试一个小问题,这就是我组装的雅可比矩阵是否实际产生了正确的全局雅可比矩阵。我还想针对已知的全局右侧测试我的右侧功能。每个此类测试仍应仅在应用程序(例如,在PETSc,测试RHSFunctionRHSJacobianin ${PETSC_DIR}/src/ts/examples/tutorials/ex.2)中单独行使单个功能。
Geoff Oxberry 2013年

我认为目前不存在可以帮助您完成所需工作的框架。我们已经设法在PyClaw中纠缠于为我们做一些事情(Lisandro在mpi4py和petsc4py中使用了它)。您是否看过mpich中的测试框架?
阿隆·艾玛迪亚

Answers:


8

我很高兴在CMake / CTest构建环境中使用C ++ MPI代码的GoogleTest用户:

  • CMake自动从svn安装/链接googletest!
  • 添加测试是单线的!
  • 编写测试很容易!(和谷歌模拟是非常强大的!)
  • 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。


4

有几个启用MPI的软件包使用CMake工具集进行测试。我想到的就是Trilinos,VTK和ParaView。我想您不想假设该可执行文件需要使用mpirun和/或mpiexec启动。CMake支持指定如何正确启动可执行文件以及不同的选项,例如使用的最大进程数以及必要时的前标志和后标志。

您可能希望查看ParaView仪表板的“ HPC站点”部分,其中的测试在各种NERSC和Argonne超级计算机上运行。内置了大多数设置,您需要指定这些设置才能使其在这些计算机上正常工作。

作为参考,Trilinos仪表板列出了各种各样的软件包,对我而言,其组织结构令人印象深刻。

全面披露:我是Kitware的一名员工,CMake是Kitware参与的开源项目之一。


感谢您的回答!我一直在看CTest,除了KitWare网站上类似手册页的描述外,没有看到任何文档。您可以推荐任何免费的教程吗?
Geoff Oxberry 2013年

CMake Wiki上有很多信息。那里有很多针对CMake,CTest和CPack的教程。我在Stack Overflow上找到了这些应用程序的大部分答案。
andybauer 2013年

andybauer-感谢您的回答。您介意编辑答案并公开与KitWare的隶属关系吗?
Aron Ahmadia 2013年

3

我们只需要在Deal.II中滚动自己的代码即可。II-本质上,我们告诉框架使用来执行测试mpirun -np ...。我们以前只是使用基于Makefile的测试方案(编译,链接,执行测试,然后将输出与以前保存的输出进行比较),您可以在这里找到:

对于上下文,非MPI目标在此处:

我们正在使用CMake / CTest重写事物,当前的开发如下:


沃尔夫冈,谢谢您的回答!PETSc似乎做类似的事情。
Geoff Oxberry 2013年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.