添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

将python嵌入到fortran 90中

8 人关注

我正在考虑将python嵌入fortran90中,为我现有的fortran90代码添加python功能。我知道可以通过使用numpy的f2py在fortran90中扩展python来实现。但是,我想把我的超级优化的主循环保留在fortran中,并在我能用fortran做之前加入python来做一些额外的任务/评估进一步的发展,同时也是为了简化代码的维护。我正在寻找以下问题的答案。

1) 是否有一个已经存在的库,我可以将python嵌入到fortran中? 我知道f2py,它是以另一种方式进行的。 2) 我们如何处理从fortran到python和返回的数据传输? 3) 我们怎样才能实现回调功能?(让我描述一下这个场景:.... 我在Fortran中的main_fortran程序,在python中调用Func1_Python模块。现在,从这个Func1_Python中,我想调用另一个函数......比如Fortran中的Func2_Fortran) 4) 将python的解释器嵌入fortran中,在性能方面会有什么影响....,运行时间,发送数据(双精度的大数组)等。

非常感谢您的帮助!!!。

编辑1。我想通过增加一些关于我正在做的工作的信息来确定讨论的方向。我是做科学计算的。所以,我将会在巨大的数组/矩阵上进行大量的双精度工作,并进行浮点运算。所以,除了fortran之外,很少有其他的选择来为我做这些工作。我想在我的代码中加入python的原因是,如果有必要,我可以使用NumPy做一些基本的计算,并以最小的努力扩展代码的能力。例如,我可以使用几个可用的库来连接python和其他一些包(比如说OpenFoam使用PyFoam库)。

2 个评论
如果你打算使用sympy。 check this
除非你要做的是字符串操作,否则Fortran可能比Python做得更快。
python
fortran
embed
Ravi
Ravi
发布于 2013-06-13
7 个回答
ylikx
ylikx
发布于 2018-09-03
已采纳
0 人赞同

我已经开发了这个图书馆 Forpy 它允许你在 Fortran 中使用 Python(嵌入)。 它使用 Fortran C 互操作性来调用 Python C API 函数。

虽然我同意扩展(在Python中使用Fortran)往往是更好的,但嵌入也有其用途。

  • Large, existing Fortran codes might need a substantial amount of refactoring before they can be used from Python - here embedding can save development time
  • Replacing a part of an existing code with a Python implementation
  • Temporarily embedding Python to experiment with a given Fortran code: for example to test alternative algorithms or to extract intermediary results
  • 除了嵌入, Forpy 还支持扩展Python。 通过 Forpy ,你可以完全用Fortran编写一个Python扩展模块。 与现有的工具如 f2py 相比,它的优势在于你可以使用Python数据类型 (例如,编写一个以Python list为参数的函数或一个返回Python dict的函数)。

    与现有的,可能是遗留的Fortran代码一起工作通常是非常有挑战性的,我认为开发者应该有工具来嵌入和扩展Python。 我认为开发者应该有工具来嵌入和扩展 Python。

    如果你必须从fortran访问python,并且不能翻转到从python调用fortran,那么 这就是答案 .福比是非常好的。
    Alex Szatmary
    Alex Szatmary
    发布于 2018-09-03
    0 人赞同

    1. Don't do it

    我知道你想在Fortan程序中加入Python代码,而不是让Python程序带有Fortran扩展。我的第一个建议是不要这样做。Fortran在数组运算方面比Python快,但Python比Fortran更容易编写,用OOP技术扩展Python代码更容易,而且Python可能会访问对你很重要的库。你提到在Fortran中有一个超级优化的主循环;Fortran对于超级优化的 inner 循环。在Python程序中用Numpy传递一个Fortran数组的逻辑比你在Fortran中正确处理一个Python对象所要做的要简单得多。

    当我从头开始一个科学计算项目时,我总是先用Python写,找出性能瓶颈,然后将其翻译成Fortran。能够针对经过验证的Python代码测试更快的Fortran代码,可以更容易地证明代码的工作是正确的。

    由于你有现有的代码,用Fortran制作的模块来扩展Python代码将需要重构,但这个过程应该是很简单的。将初始化代码从主循环中分离出来,将循环分解成逻辑片段,将这些例程分别包裹在一个Python函数中,然后你的主Python代码可以调用Fortran子程序,并酌情将这些子程序与Python函数交错。在这个过程中,你也许可以保留你在Fortran中的主循环中的很多优化。F2PY是一个相当标准的工具,所以找到能够帮助你解决任何问题的人并不难。

    2. System calls

    如果你绝对要让Fortran代码调用Python代码,而不是反过来,最简单的方法是让Fortran代码写一些数据到磁盘,然后用 SYSTEM EXECUTE_COMMAND_LINE 运行Python代码。如果你使用 EXECUTE_COMMAND_LINE ,你可以让Python代码将其结果输出到stdout,Fortran代码可以将其作为字符数据读取;如果你有大量的输出(例如,一个大的矩阵),Python代码输出一个文件,然后由Fortran代码读取会更合理。磁盘读/写的开销可能会非常大。另外,你必须写Fortran代码来输出你的数据,Python代码来读取它,Python代码再次输出它,Fortran代码重新输入数据。这段代码的编写和测试应该很简单,但是在你编辑代码时保持这四个部分的同步可能会变成一个令人头痛的问题。

    (这种方法在 这个Stack Overflow问题 )

    3. Embedding Python in C in Fortran

    据我所知,没有办法直接将内存中的 Python 对象传递给 Fortran。然而,Fortran 代码可以调用 C 代码,而 C 代码可以将 Python 嵌入其中。(见 关于扩展和嵌入的 Python 教程 .)一般来说,扩展 Python (就像我在第 1 点中建议的那样) 比把它嵌入 C/C++ 中要好。(见 Extending Vs. Embedding: There is Only One Correct Decision .)要想让它工作将是一场噩梦,因为Python和Fortran之间的任何通信问题都可能发生在Python和C之间,或者C和Fortran之间。我不知道是否有人真的将Python嵌入到C的Fortran中,因此获得帮助会很困难。

    Ravi
    Hello alex, Thank you for your very comprehensive answer. I was also looking at the Fortran-> C -> Python option....I will be posting results of scale up for extending python with fortran vs embedding python into fortran in a few days.
    有大量的C/C++程序嵌入了pzthon解释器。当然Lua或Guile更容易嵌入,但社区里的人更多。使用适当的C/Fortran互操作性,在C或Fortran中嵌入程序应该没有什么区别。
    虽然我知道Alex的心是对的,但他可以不提第1和第2点。绿地Fortran编程是很罕见的,当人们问及在Fortran中嵌入一种语言时,那是因为核心代码必须保留在Fortran中,这是出于实用主义的原因(例如,质量保证、速度、没有什么资源可以从头开始用另一种语言编写、开发人员的核心能力)。没有人把嵌入一种语言作为一种随意的练习。同样地,启动system()调用很可能是不安全的,也是不可移植的,所以有很好的理由不这样做。
    arclight
    arclight
    发布于 2018-09-03
    0 人赞同

    如果你要在 Fortran 中嵌入 Python,你必须通过 Fortran 的 C 接口来实现;这就是 ISO_C_BINDING 的作用。我想提醒大家不要嵌入 Python,不是因为这样做的技术难度,而是因为 Python (语言或社区) 似乎坚决反对把 Python 作为附属语言使用。普遍的观点是,无论你目前用什么非Python语言编写的代码,都应该被分解成库,用来扩展Python,而不是反过来。所以你会看到(就像这里)更多的回应,试图说服你,你真的不想要做你的事情 实际上 想做的事,而不是实际的技术援助。

    这不是煽动,也不是社论,更不是做道德判断;这只是一个简单的事实陈述。如果你试图嵌入 Python,你将不会从 Python 社区得到帮助。

    如果你所需要的功能超出了Fortran语言本身所支持的范围(例如文件系统操作) 你并不特别需要Python you want a language more expressive than C, you may want to look at embedding Lua instead. Unlike Python, Lua is specifically meant to be embedded so you are likely to face much less social 和 technical resistance.

    有一些项目是 integrate Fortran 和 Lua ,迄今为止,我所看到的最完整的一个是 Aotus . The author is very responsive 和 the integration process is simple.

    Admittedly, this does not answer the original question (how to embed a Python interpreter in a Fortran 90 application) but to be fair, none of the other responses do either. I use Python as my portable general-purpose language of choice these days 和 I'd really prefer to stick with it when extending our primary products (written in Fortran). For the reasons laid out above, I ab和oned my attempts to embed Python 和 switched to embedding Lua; for social reasons, I feel Lua is a much better technical choice. It's not my first choice but it's workable, at least in my case.

    如果我冒犯了任何人,请原谅;我不是要挑起争端,只是在研究这个特定的主题时,介绍我的经验。

    Ravi
    谢谢你的回答。我同意你所说的。Python不是为嵌入另一种语言而制造的,因此,对这样做的支持微乎其微/没有。然而,从科学计算的角度来看,Python具有很高的兴趣,特别是由于像NumPy和SciPy这样的计算包超过了它的所有其他优势。我确实想出了一个办法,通过在嵌入和扩展之间做某种混合,来取两者的精华。你可以看一下我上面的回答。
    在我的工作环境(工程分析)中,Python是我进行普通计算和低性能数值计算的选择。在这里,软件是由主题专家(通常是核、化学和机械工程师)编写的,他们的主要语言是Fortran,而不是由计算机科学家。将我们的主要编程语言从Fortran切换到Python是不可能的,这有坚实的技术和组织原因。我宁愿避免引入第三种语言,但Lua对我们的需求来说是一个更好的选择。YMMV。
    Ravi
    Ravi
    发布于 2018-09-03
    0 人赞同

    我已经尝试了几种方法来解决这个问题,我已经找到了一种可能是最佳的方法。我将简要地列出这些方法和结果。

    1) 通过系统调用进行嵌入。每当我们想从fortran访问python时,我们就使用系统调用来执行一些python脚本,并在它们之间交换数据。这种方法的速度受到磁盘读、写的限制(在这个对代码进行缓存级优化的时代,进入磁盘是一种致命的错误)。另外,我们每次要执行脚本时都需要初始化解释器,这也是一笔不小的开销。一个简单的Runge Kutta四阶方法运行了300个时间步数,执行时间高达59秒。

    2) 通过C从Fortran到Python:我们使用ISO_C绑定在Fortran和C之间进行通信;我们在C中嵌入Python解释器。不过为了完整起见,我还是想评估一下。

    3) 使用f2py将Fortran子程序导入Python(扩展)。 在这里,我们将主循环从Fortran中取出,并在Python中编码(这种方法被称为用Fortran扩展Python);我们用f2py将所有Fortran子程序导入Python ( http://cens.ioc.ee/projects/f2py2e/usersguide/ ).我们可以灵活地将任何科学应用中最重要的数据,即最外层的循环(一般是时间循环)放在Python中,这样我们就可以将其与其他应用结合起来。但是,我们也有一个缺点,就是必须在Fortran和Python之间交换可能超过需要的数据。同样的Runge Kutta四阶方法例子的执行时间为0.372秒。

    4) 通过扩展模仿嵌入。 到目前为止,我们已经看到了Embedding(主循环停留在fortran中,我们根据需要调用python)和Extending(主循环停留在python中,我们根据需要调用fortran)这两种纯方法。还有一种方法,我发现它是最理想的。将主循环的部分内容转移到Python中会导致开销,这可能不是一直都需要的。为了摆脱这种开销,我们可以保留 Fortran 中的主循环,它被转换成一个子程序,不做任何改动,在 Python 中有一个伪主循环,它只是调用 Fortran 中的主循环,程序的执行就像我们未经处理的 Fortran 程序。每当需要时,我们可以使用回调函数,带着所需的数据回到Python,执行一个脚本,然后再回到Fortran。在这种方法中,Runge Kutta四阶方法花了0.083秒。我对代码进行了剖析,发现python解释器的初始化和加载花了0.075秒,程序只花了0.008秒(其中包括对python的300个回调函数)。而原来的fortran代码则需要0.007秒。因此,使用这种方法,我们几乎可以得到类似Fortran的性能和类似python的灵活性。

    这种方法(第4条)对你来说效果如何?你是否有一个可以分享的repo例子?
    Paul Wells
    Paul Wells
    发布于 2018-09-03
    0 人赞同

    有一个非常简单的方法可以使用 f2py 来做到这一点。编写你的Python方法并将其作为输入添加到你的Fortran子程序中。在 cf2py 钩子和类型声明中都声明为 EXTERNAL ,并声明其返回值类型,例如: REAL*8 。然后,你的Fortran代码将有一个指向存储python方法的地址的指针。这将是很慢的,但对于测试算法来说,它是很有用的。我经常这样做(我把很多古老的意大利语Fortran移植到python模块中......),这也是在传统Fortran中使用优化的Scipy调用的一个好方法

    jhrmnn
    jhrmnn
    发布于 2018-09-03
    0 人赞同

    我刚刚成功地将Python嵌入到我们内部的~500 KLOC Fortran程序中,并使用了 cffi .一个重要的方面是不要碰现有的代码。该程序是用Fortran 95编写的。我使用 iso_c_binding 模块写了一个薄薄的2003包装器,它只是从各种模块中导入数据,获得这些数据的C指针和/或将Fortran类型包装成C结构,将所有东西放入一个类型/结构中,并发送给一个C函数。这个 C 函数恰好是一个用 cffi 包装的 Python 函数。它把C结构解压成一个更方便的Python对象,把Fortran数组包装成Numpy数组(没有复制),然后根据用户的配置,落入一个交互式Python控制台或运行一个Python脚本。除了一个头文件,不需要写C代码。显然有一些开销,但这个功能是为了扩展,而不是为了性能。

    我建议不要使用f2py。它没有得到很好的维护,严重限制了你的Fortran代码的公共接口。

    Laurent Pointal
    Laurent Pointal
    发布于 2018-09-03
    0 人赞同