在R中高效调用F95:使用.Fortran或.Call?

问题描述 投票:4回答:2

我正在编写一些R模拟代码,但希望利用Fortran的swift线性代数库来替换核心迭代循环。到目前为止,我主要关注使用.Fortran调用链接的F95子例程的明显选项;我想我应该优化内存使用(我传递的是非常大的数组)并设置DUP=FALSE,但后来我在手册中读到了关于这种方法的危险性及其在R 3.1.0中的折旧和R 3.2.0中的禁用的警告。现在手册建议切换到.Call,但此功能本身不提供Fortran支持。

我的谷歌搜索产生了a stackoverflow question,探索了一种通过C代码链接Fortran子程序和使用.Call调用它的方法。在我看来,这种事情可能像魅力或诅咒一样起作用。因此,我的问题:

  1. 为了速度和稳健性,通过.Fortran.Call调用Fortran的风险和好处是什么?
  2. 有没有更优雅/有效的方法使用.Call来调用Fortran子程序?
  3. 还有其他选择吗?
c r dll fortran
2个回答
2
投票

以下是我对这种情况的看法:

.Call是一般首选的界面。它直接为您提供了指向底层R数据对象(SEXP)的指针,因此您决定进行所有内存管理。您可以尊重NAMED字段并根据需要复制数据,或忽略它(如果您知道您不会修改数据,或者由于其他原因而感到很舒服)

.Fortran尝试从R SEXP对象自动提供适当的数据类型到Fortran子例程;但是,一般不鼓励使用它(原因我并不完全清楚,说实话)

你应该有一些运气从C / C ++例程调用编译的Fortran代码。给定一个名为fortran_subroutine的Fortran子例程,您应该能够在C / C ++代码中提供前向声明,例如: (注意:你需要一个领先的extern "C"用于C ++代码):

void fortran_subroutine_(<args>);

注意函数名称上的尾随下划线 - 这正是Fortran编译器(我熟悉的,例如gfortran)默认情况下的'mangle'符号名称,因此可用的符号将具有该尾随下划线。

此外,您需要确保选择的<args>映射到相应的C类型到相应的Fortran类型。幸运的是,R-exts提供了这样一张桌子。

最后,R的R CMD build将自动促进R包的编译+链接过程。因为我显然是一个贪婪的惩罚,我有produced an example package应该提供足够的信息,让你了解绑定如何在那里工作。


2
投票

3.还有其他选择吗?是

R包dotCall64可能是一个有趣的选择。它提供.C64(),它是外部函数接口的增强版本,即.C().Fortran()

接口.C64()可用于连接Fortran和C / C ++代码。它

  • 有类似.C().Fortran()的用法
  • 提供了一种机制来避免不必要的只读和只写参数副本
  • 支持长向量(具有超过2 ^ 31-1个元素的向量)
  • 支持64位整数类型参数

因此,可以避免不必要的只读参数副本,同时避免将.Call()接口与C包装函数结合使用。

一些链接:

我是dotCall64和垃圾邮件的作者之一。

© www.soinside.com 2019 - 2024. All rights reserved.