将python回调函数传递给Fortran子例程的开销是多少?

2024-10-02 12:38:49 发布

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

我刚刚用F2PY将一个fortran90子例程打包到python中。这里的精妙之处在于Fortran子例程aslo将python回调函数作为其参数之一:

SUBROUTINE f90foo(pyfunc, a)
real(kind=8),intent(in) :: a
!f2py intent(callback) pyfunc
external pyfunc
!f2py real*8 y,x
!f2py y = pyfunc(x)

!*** debug begins***
print *, 'Start Loop'
do i=1,1000
  p = pyfunc(a)
end do
total = etime(elapsed)
print *, 'End: total=', total, ' user=', elapsed(1), ' system=', elapsed(2)
stop
!*** debug ends  ***

pyfunc是在我的python代码中定义的一个python函数。包装器工作得很好,但是运行上面的包装版本,我得到的运行时间大约是纯python的5倍,如下所示

^{pr2}$

所以,问题是,管理费用是怎么来的?我真的想让pyfunc保持原样,因为将其重新编码为纯fortran函数非常耗时,那么有没有任何方法可以提高包装器模块的速度?在


Tags: 函数debug例程dorealtotalprintfortran
1条回答
网友
1楼 · 发布于 2024-10-02 12:38:49

在您发布的代码中,a是双精度浮点。将它从Fortran传递到Python意味着将Fortran double包装到PyFloat对象,这确实有代价。在纯Python版本中,k是一个PyFloat,您不必为包装它1000次而付出代价。在

另一个问题是函数调用本身。从C调用Python函数在性能上已经很差,但是从Fortran调用它们就更糟糕了,因为有一个额外的代码层可以将Fortran函数调用约定(关于堆栈等)转换为C函数调用约定。从C调用Python函数时,需要将参数准备为Python对象,一般创建PyTuple对象作为Python函数的*args参数,在模块表中查找得到函数指针。。。在

最后但并非最不重要的一点:在Fortran和Numpy之间传递2D数组时,需要注意数组的顺序。F2py和numpy在这方面可能很聪明,但是如果Python代码不是按照Fortran顺序来操作数组的,那么性能就会受到影响。在

我不知道pyfunc要做什么,但是如果它与您发布的内容很接近,那么用Python编写循环并只调用一次函数将节省您的时间。如果需要中间值(p),让Python函数返回一个包含所有中间值的Numpy数组。在

相关问题 更多 >

    热门问题