Python unittest C/Fortran MPI函数导致在MPI_finalize后调用MPI_Init函数

2024-09-29 22:00:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一个使用MPI(OpenMPI,如果相关的话)的Fortran库编写Python包装。我在这里提到的问题也恰恰发生在Python包装器到C库的情况下。我必须使用内置的unittestPython包来测试Python接口

我有下面的MWE,它试图在所有处理器中找到最大和最小整数。以下是Fortran文件:

! File mpitest.F90
module mpitest
    implicit none
    include "mpif.h"
    integer nranks
    integer rank

    contains

    !--------------------------------------------------!
    subroutine pympitest_init()
        implicit none
        integer ierror
        call MPI_INIT(ierror)
        call MPI_COMM_SIZE(MPI_COMM_WORLD, nranks, ierror)
        call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierror)
    end subroutine pympitest_init

    !--------------------------------------------------!
    subroutine get_max_integer(inint, outint)
        implicit none
        integer, intent(in) :: inint
        integer, intent(out) :: outint
        integer ierror
        call mpi_allreduce(inint,outint,1,mpi_integer,mpi_max,MPI_COMM_WORLD,ierror)
    end subroutine get_max_integer

    !--------------------------------------------------!
    subroutine get_min_integer(inint, outint)
        implicit none
        integer, intent(in) :: inint
        integer, intent(out) :: outint
        integer ierror
        call mpi_allreduce(inint,outint,1,mpi_integer,mpi_min,MPI_COMM_WORLD,ierror)
    end subroutine get_min_integer

    !--------------------------------------------------!
    subroutine pympitest_final()
        integer ierror
        call mpi_finalize(ierror)
    end subroutine pympitest_final

end module mpitest

下面给出了Python单元测试文件,其中有些内容我已经尝试过,但没有作为注释加入:

#!/usr/bin/env python3
# Python file test_pympitest.py
from __future__ import print_function
import unittest
import numpy as np

from pympitest import mpitest as pm

#--------------------------------------------------------------------#
class Test_Fortran_MPI_functions(unittest.TestCase):
    """Unit test template for testing MPI functions."""

    #----------------------------------------------------------------#
    #def __init__(self):
    #    """Try MPI_Initialize -- Does not help."""
    #    print("Initializing MPI")
    #    pm.pympitest_init()

    #----------------------------------------------------------------#
    #def tearDown(self):
    #    """Try MPI_Finalize -- Does not help."""
    #    print("Finalizing MPI")
    #    pm.pympitest_final()

    #----------------------------------------------------------------#
    def setUp(self):
        """Initialize the unit test."""
        print("Initializing MPI")
        pm.pympitest_init()

        # We'll just test min. and max. of ranks across all PEs.
        self.inint = pm.rank

    #----------------------------------------------------------------#
    def tearDown(self):
        """Finalize the unit test."""
        print("Finalizing MPI")
        pm.pympitest_final()

    #----------------------------------------------------------------#
    #----------------------------------------------------------------#
    # Two Tests. If you comment out any one of the tests, then the
    # unit test runs fine. Keeping both uncommented thorws error
    # saying MPI_Init was called after MPI_Final, obviously since
    # the setUp and tearDown functions are called every time.
    #----------------------------------------------------------------#
    def test_get_min_integer(self):
        """Test get_min_integer function."""
        minint = pm.get_min_integer(self.inint)
        print("Minimum on processor {} = {}".format(pm.rank,minint))
        self.assertEqual(minint, 0)

    #----------------------------------------------------------------#
    def test_get_max_integer(self):
        """Test get_max_integer function."""
        maxint = pm.get_max_integer(self.inint)
        print("Maximum on processor {} = {}".format(pm.rank,maxint))
        self.assertEqual(maxint, pm.nranks-1)

#--------------------------------------------------------------------#
if __name__ == "__main__":
    unittest.main()

    # Tried the following. Does not help:
    # Calls MPI_Initialize but exits without calling MPI_Finalize.
    #print("Initializing MPI")
    #pm.pympitest_init()
    #unittest.main()
    #print("Finalizing MPI")
    #pm.pympitest_final()

Fortran代码使用f2py包装到名为pympitest的Python模块中,如下所示: f2py --f90exec="mpif90" -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -c mpitest.F90 -m pympitest。单元测试在4个处理器上运行,如:mpirun -np 4 python test_pympitest.py

我希望将所有MPI单元测试保存在一个python文件中。在我尝试过的不同方法中(请参阅Python文件中的注释),我遇到的问题是MPI_Initialize和MPI_Finalize要么在一次运行中多次被调用,要么只调用其中一个,所有这些方法都会以错误退出

如何修复此问题以使单元测试正确通过


Edit(添加):将测试函数放在单个Python文件中单独的Test_...(unittest.TestCase)类中也没有帮助。将MPI单元测试拆分为不同的文件并尝试python -m unittest discover不起作用,这很不方便。测试每个Python文件的单个包装MPI函数并单独运行每个Python文件都可以,但这是我宁愿避免的事情


Tags: 文件testselfgetintegerminmaxprint
1条回答
网友
1楼 · 发布于 2024-09-29 22:00:29

aunittest.TestCasesetUp()tearDown()方法为每个试验方法设置和拆卸提供。您应该期望前者在每个测试方法之前执行,后者在每个测试方法之后执行

相反,您似乎希望对类中的整个测试方法集合分别执行一次。为此,您需要setUpClass() and tearDownClass()。或者,如果您定义了多个测试类,那么您可能更喜欢setUpModule()tearDownModule()

或者,您可以创建一个^{}子类来运行测试,并重写它的run()方法以对所有安装和拆卸执行一次

相关问题 更多 >

    热门问题