在 R 包中包含 TMB C++ 代码的指南

RTb*_*ard 3 c++ r tmb

我最近发现了 TMB 的神奇之处,并且正在开发一个包,最好在其中包含 TMB c++ 模板,以用于计算成本相当高的模型。

我假设有可能:

  • 在软件包安装时自动编译 TMB 源代码

但我在 TMB 文档中找不到与此相关的任何明确指南。到目前为止,我的替代方案是编写在第一次调用使用未编译类的函数时编译 TMB 代码的函数……但我感觉有更好的方法可以做到这一点。

有没有人成功地将 TMB 函数包含在另一个包中,并且可以为我指出相关文档或示例的方向?

RTb*_*ard 5

经过更多搜索,我终于在这个帖子中找到了答案。我想我错过了它,因为它详细说明的解决方案已移至名为development的 wiki 页面,其中内容专门针对希望为 TMB 的开发做出贡献的用户,而我只想分发包含 TMB 的代码。

总而言之,该线程建议我采用这样的一些更改(myPkg应该是您的包的名称):

源代码/

  • 将您的.cpp模板放入mypkg/src. 当您构建包时,R 将自动编译它。

描述

将这些行添加到您的描述文件中,以便 R 拥有编译模型模板所需的所有工具。

Depends: TMB, RcppEigen
LinkingTo: TMB, RcppEigen
Run Code Online (Sandbox Code Playgroud)

R/roxygentags.r

现在我们需要将 TMB 模板添加到命名空间文件中。我们可以通过 roxygen 制作一个虚拟文件,如下所示轻松完成此操作:

#' Roxygen commands
#'
#' @useDynLib myPkg
#'
dummy <- function(){
  return(NULL)
}
Run Code Online (Sandbox Code Playgroud)

虚拟函数只是将标签放在@useDynLib myPkg我的源代码中的某个地方的借口,这样我就不会弄乱它。该标签将用...填充您的命名空间useDynLib(myPkg),据我了解,这会在为您加载包时加载共享库。

调用包中的函数:

最后,调用时MakeADFun,设置DLL="myPkg"。通过此设置,您可以将单个TMB 模型编译到您的包中。这是因为您文件夹中编译的内容./src/将根据您的包名称自动重命名,因此您无法创建唯一命名的模型。

编辑:分发多个 DLL 的解决方案

经过更多搜索(与上面引用的相同线程)...我意识到官方 wiki 中描述的解决方案(以及上面详细介绍的)仅与分发单个 dll(即单个 TMB 模型)相关。

如果您想在一个包中分发多个 TMB 模型,则必须使用您自己的 makefile。我在我的博客中给出了更详细的描述,因此我将仅简要描述此处的步骤,了解它们与我之前描述的步骤有何不同。

源文件/生成文件

您必须定义自己的Makefile(或Makefile.win针对 Windows 用户)并将其放入您的src/目录中。这是一个对我有用的例子:

all: template1.so template2.so
    # Comment here preserves the prior tab
template1.so: template1.cpp
    Rscript --vanilla -e "TMB::compile('template1.cpp','-O0 -g')"
template2.so: template2.cpp
    Rscript --vanilla -e "TMB::compile('template2.cpp','-O0 -g')"

clean:
    rm -rf *o 
Run Code Online (Sandbox Code Playgroud)

对于 Windows,将so、 替换为dll,并使用相关编译器标志(用于调试)。?TMB::compile有关调试编译器标志的信息,请参阅参考资料。

R/roxygentags.r

这与上面略有不同:

#' Roxygen commands
#'
#' This is a dummy function who's purpose is to hold the useDynLib roxygen tag.
#' This tag will populate the namespace with compiled c++ functions upon package install.
#'
#' @useDynLib template1
#' @useDynLib template2
#'
dummy <- function(){
  return(NULL)
}
Run Code Online (Sandbox Code Playgroud)

使用包中的模型

最后,上述更改将编译多个唯一命名的 TMB 模板并将它们加载到命名空间中。要在包中调用这些模型,下面是一个示例:

obj <- MakeADFun(data = data,
                   parameters = params,
                   DLL="template1", 
                   inner.control = list(maxit = 10000),
                   silent=F)
Run Code Online (Sandbox Code Playgroud)

尖端...

当我尝试在 Windows 机器上编译此文件时,我遇到了问题...结果证明与未正确清理 src 文件夹有关,并且我将旧的 linux 编译文件卡在了那里。如果您遇到编译问题,值得手动清除src/目录中以前版本中的残留文件...或者也许有人可以提供一些关于编写更好的 make 文件的好建议!