我有一个复杂的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类。