使用Fortran函数的多个实例以及Python

时间:2018-02-09 19:57:14

标签: python fortran cython

我有一个复杂的Fortran代码已经用Cython包装,可以从Python调用它。 Fortran代码非常复杂,并且在内部为所有计算分配了许多数组(它是Fortran 90/2003)。在调用包装器之前,数组的大小是先验已知的,并且通过调用初始化子例程c_init来初始化它们。我用于Cython编译的pxd文件如下所示(为简化帖子而删节的所有内容):

from numpy cimport ndarray as ar
from numpy import emptyzeros

cdef extern:
    void c_synth(int* mode, double* BInput, [and more parameters...])
    void c_init(int* n)

def _synth(int mode=5, ar[double,ndim=1] BInput=zeros(3)):
    cdef:
        ar[double,ndim=1] out = empty(n, order='F')


    c_synth(&mode, &BInput, <double*> out.data)

def _init(int n=100):
    c_init(&n)

Fortran 90源代码(仅与此处相关的部分)为:

module test
use iso_c_binding, only: c_int, c_double
use vars
implicit none

contains
subroutine c_synth(mode, BInput, out) bind(c)
    integer(c_int), intent(in) :: mode
    real(c_double), intent(in), dimension(3) :: BInput
    real(c_double), intent(out), dimension(n) :: out

! A complex calculation that needs many allocatable arrays and
! multifile source code is done here

end subroutine c_synth

subroutine c_init(n) bind(c)
    integer(c_int), intent(in) :: n

! Many allocatable arrays are initialized here plus some data that need to be 
! read only once

end subroutine c_synth

现在,我正在使用Python代码中包装的Fortran代码来执行不同大小的可分配数组的同时计算,因此前面代码中的n将不同于调用呼叫。如果我只是简单地从Python导入Cythonized包装器并多次调用_init(n),那么Fortran代码将仅使用上次调用时n的值。

作为一个时间解决方案,我已经修改了我的Fortran代码,以便每次运行具有不同n值的代码时动态解除分配/重新分配内存,但这使得效率不高。我想在内存中运行几个包装器实例,可以从Python高效调用,而无需分配/释放内存。我尝试过的另一个选项是使用`mpmportlib``对包装器的导入进行monkeypatch,但所有导入的模块都共享相同的Fortran代码。

我的问题是:有没有办法封装Fortran代码以运行多个实例?我甚至尝试构建一个封装_synth_init方法的Cython类。

0 个答案:

没有答案