19

我有一个 R 包,它使用大量 Fortran 子例程来进行递归线性代数计算的嵌套循环(很大程度上取决于 BLAS 和 LAPACK 例程)。作为 Fortran 的接口,我使用.Fortran函数。我刚刚阅读了Jonathan Callahan 的关于使用而不是使用 C/C++ 编写的子例程的博客文章,这让我想到,在使用 Fortran 子例程时也使用接口会更好,方法是在 C 中编写一个简单的包装器,然后调用Fortran 子程序?.Call.C.Call

如前所述,我的 Fortran 代码在某种意义上非常简单,我只是使用双精度或整数类型的多维数组。但是我了解到我必须在 R 端写很多检查以确保一切都不会崩溃,因为我不小心忘记将某些矩阵的存储模式更改为整数或某些矩阵的维度已更改等。

子程序写为 F90/95。

4

2 回答 2

5

如果您使用大型数据集,可能会有优势。.Call 可以更快,因为您每次调用函数时都不会复制数据。对于这个问题中描述的情况,不会有这样的优势,因为 R 2.15.1 发行说明状态

.C() 和 .Fortran() 复制较少:未命名的原始、逻辑、整数、实数或复数向量的参数在调用之前不会被复制,并且(无论是否命名)在调用之后不会被复制。列表不再被复制(它们应该在 C 代码中以只读方式使用)。

切换到 .Call 意味着您放弃了 .Fortran 接口的便利性。您将 SEXP 传递到 C 代码中,使用(可怕且没有充分记录的)R API 对数据进行任何检查/操作,然后从 C 中调用 Fortran 函数。任何使用您的代码的人都必须了解R API 和 C/Fortran 互操作。

于 2013-04-03T18:21:56.283 回答
3

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

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

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

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

一些链接:

我是dotCall64spam的作者之一。

于 2019-04-17T09:00:35.143 回答