R:使用带有.Call和C / C ++包装器的Fortran子例程代替.Fortran的优点?

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

我有一个R包,它使用大量的Fortran子程序来进行递归线性代数计算的嵌套循环(严重依赖于BLAS和LAPACK例程)。作为Fortran的接口,我使用.Fortran函数。在C / C ++编写的子程序中,我只是读Jonathan Callahan's blog post关于使用.Call而不是.C,它让我觉得在使用Fortran子程序时使用.Call接口更好,在C中编写一个简单的包装然后调用Fortran子程序?

如上所述,我的Fortran代码非常简单,因为我只使用double或integer类型的多维数组。但我已经知道我必须在R端编写相当多的检查以确保一切都不会崩溃,因为我不小心忘记将某些矩阵的存储模式更改为整数或某些矩阵的维度已更改等。

子程序写为F90 / 95。

c performance r fortran wrapper
2个回答
4
投票

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

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

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


2
投票

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.