首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将TMB c++代码包含在R包中的指南

将TMB c++代码包含在R包中的指南
EN

Stack Overflow用户
提问于 2018-02-05 16:28:26
回答 2查看 1.1K关注 0票数 3

最近,我发现了TMB的神奇之处,我正在开发一个包,该包理想地将TMB c++模板包括在其中,用于计算成本较高的模型。

我认为有可能:

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

但我在TMB文档中找不到有关这方面的任何明确指导方针。到目前为止,我的替代方法是编写函数,在使用未编译类的函数的第一次调用时编译TMB代码.但我觉得有更好的方法来做这件事。

是否有人成功地将TMB功能包含在另一个包中,并能指出相关文档或示例的方向?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-05 20:12:50

通过更多的搜索,我终于在这个线程中找到了我的答案。我想我错过了它,因为它的细节被移到了名为“开发”的wiki页面,其中的内容专门针对希望为TMB的开发做出贡献的用户,而我只想分发与TMB不一致的代码。

总之,这个线程建议我这样做(myPkg应该是您的包的名称):

src/

  • .cpp模板放置在mypkg/src中。在您构建包时,这将由R自动编译。

描述

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

代码语言:javascript
复制
Depends: TMB, RcppEigen
LinkingTo: TMB, RcppEigen

R/roxygentags.r

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

代码语言:javascript
复制
#' Roxygen commands
#'
#' @useDynLib myPkg
#'
dummy <- function(){
  return(NULL)
}

这个虚拟函数只是我的源代码中某个地方有标记@useDynLib myPkg的借口,在这里我不会处理它。此标记将使用命名空间填充useDynLib(myPkg)..。正如我所理解的,在为您加载包时,这会加载共享库。

调用包中的函数:

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

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

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

如果要在一个包中分发多个TMB模型,则必须使用自己的makefile。我已经给出了一个更详细的描述在我的博客里,因此我只简要地描述这些步骤与前面所描述的步骤有何不同。

src/Makefile

您必须定义自己的Makefile (或windows用户的Makefile.win ),并将其放到src/目录中。下面是一个对我有用的例子:

代码语言:javascript
复制
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 

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

R/roxygentags.r

这与上述略有不同:

代码语言:javascript
复制
#' 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)
}

在包中使用您的模型

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

代码语言:javascript
复制
obj <- MakeADFun(data = data,
                   parameters = params,
                   DLL="template1", 
                   inner.control = list(maxit = 10000),
                   silent=F)

小费..。

我在windows机器上编译这个的时候遇到了问题.事实证明,这与不正确地清理src文件夹有关,我的旧linux编译文件被卡在里面。如果您有编译问题,需要手动清除src/目录中以前构建的剩余文件.或者有人可以给一些好的建议,写一个更好的制作文件!

票数 5
EN

Stack Overflow用户

发布于 2020-09-30 12:59:31

如果您希望使用来自TMB的附加代码访问CppAD库(这是相当可观的!)然后您可以使用WITH_LIBTMB宏变量,就像我在这个标头这里中所做的那样。这将允许您拥有多个.cpp文件,您可以分别编译这些文件。重要的是,您只需要使用像这样的文件编译一次TMB头中的代码,这是#include的TMB.hpp头,而不定义WITH_LIBTMB

这大大减少了编译时间,因为您可以自己编译每个.cpp,而不需要在TMB.hpp中声明所有代码。此外,如果像我在链接中所做的那样,取消定义和定义一些宏,您也可以使用Rcpp的代码。

您还可以有一个可以由TMB::MakeADFun使用的文件。它需要一些手工操作,但也可以使用Rcpp,方法是使用Rcpp::compileAttributes并将创建的文件RcppExports.cpp改为init.cpp,然后在CallEntries数组和R_init_survTMB函数中包括以下附加行:

关于使用Rstudio的注意事项

每次构建时,Rstudio都调用Rcpp::compileAttributes (或类似的东西)。因此,您不能使用这个。一种方法是创建一个定制的构建脚本类似于这里的那个。它在删除了由R CMD INSTALL创建的RcppExports.cpp文件之后,本质上调用了Rcpp::compileAttributes。我也喜欢通过调用devtools::test()来运行测试,但是如果您愿意,可以删除它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48627069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档