R中F95的高效调用:使用.Fortran还是.Call?

Efficient calling of F95 in R: use .Fortran or .Call?

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

我的谷歌搜索 a Whosebug question 探索了一种通过 C 代码 链接 Fortran 子例程 并使用 .Call 调用它的方法。在我看来,这似乎是一种既可以像魅力也可以像诅咒一样起作用的东西。因此,我的问题是:

  1. 以速度和健壮性为目标,通过 .Fortran.Call 调用 Fortran 的风险和好处是什么?
  2. 有没有更elegant/efficient的方法使用.Call调用Fortran子程序?
  3. 还有别的选择吗?

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

.Call 是通常首选的接口。它直接为您提供了一个指向底层 R 数据对象 (a SEXP) 的指针,因此所有的内存管理都由您来决定。您可以尊重 NAMED 字段并根据需要复制数据,或者忽略它(如果您知道您不会就地修改数据,或者感觉舒适 table 为其他人这样做原因)

.Fortran 尝试自动将适当的数据类型从 R SEXP 对象提供给 Fortran 子例程;但是,通常不鼓励使用它(老实说,出于我不完全清楚的原因)

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

void fortran_subroutine_(<args>);

请注意函数名后面的下划线——这就是 Fortran 编译器(我熟悉的,例如 gfortran)默认情况下 'mangle' 符号名称的方式,因此符号是made available 将带有尾随下划线。

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

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

3。还有另一种选择吗?是

R 包 dotCall64 可能是一个有趣的选择。它提供了.C64(),它是Foreign Function Interface的增强版本,即.C().Fortran()

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

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

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

一些链接:

我是 dotCall64spam 的作者之一。