在R软件包中包含TMB C 代码的指南
Guidelines for including TMB c++ code in an R package
我最近发现了TMB的奇观,我正在研究一个包装,理想情况下将其中包括TMB C 模板以用于计算昂贵的模型。
我假设有可能:
- 在软件包安装上自动编译TMB源代码
,但我在TMB文档中找不到任何明确的准则。到目前为止,我的选择是编写在使用未编译类的函数的第一个函数上编译TMB代码的功能...但是我感觉有更好的方法可以做到。
是否有人成功地将TMB功能包括在另一个软件包中,并且可以将我指向相关文档或示例的方向?
搜索更多,我终于在此线程中找到了答案。我想我错过了它,因为IT详细信息的分辨率已移至Wiki页面,标题为 developt ,其中内容专门针对希望为TMB开发做出贡献的用户,而我只想分发代码这使TMB不正确。
总而言之,该线程建议我采用的一些更改( mypkg 应该是您的软件包的名称(:
src/
- 将
.cpp
模板放入mypkg/src
中。然后,当您构建包装时,R将自动编译。
描述
将这些行添加到您的描述文件中,因此R具有编译模型模板所需的所有工具。
Depends: TMB, RcppEigen
LinkingTo: TMB, RcppEigen
r/roxygentags.r
现在,我们需要将TMB模板添加到名称空间文件中。我们可以通过制作这样的虚拟文件来轻松地通过roxygen做到这一点:
#' 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/
目录中。这是一个对我有用的示例:
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,用dll
替换so
,并使用相关的编译器标志(用于调试(。有关调试的编译器标志的信息,请参见?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)
}
在软件包中使用模型
最后,上述更改将编译多个唯一命名的TMB模板并将其加载到名称空间中。要在包装中调用这些模型,这是一个示例:
obj <- MakeADFun(data = data,
parameters = params,
DLL="template1",
inner.control = list(maxit = 10000),
silent=F)
提示...
我尝试在Windows机器上进行编译时遇到了问题……事实证明,这与未正确清洁SRC文件夹有关,并且我将旧的Linux汇总了插在其中的文件。如果您有汇编问题,则值得手动从先前的构建中手动清理src/
目录中的剩余文件...或者,也许有人可以为编写更好的文件提供一些很好的建议!
如果要访问带有TMB的附加代码的CPPAD库(这很大!(,则可以像我在此标头中一样使用WITH_LIBTMB
宏变量。这将使您拥有多个.cpp文件,您可以单独编译。重要的是,您只需要使用此类文件来编译TMB标头的代码,该文件 #include
s tmb.hpp标头而不定义WITH_LIBTMB
。
这可以自行编译每个.cpp,而无需在tmb.hpp中声明的所有代码。此外,如果您不确定并定义了一些宏观,也可以将代码与RCPP一起使用。
。您还可以拥有一个可以使用TMB::MakeADFun
使用的文件。它需要一些手动工作,但可以通过使用Rcpp::compileAttributes
并将其更改为称为rcppexports.cpp的创建的文件命名为init.cpp,然后在CallEntries
数组和R_init_survTMB
函数中包含这些其他行:ul>
使用rstudio
注意每次构建时, rstudio调用Rcpp::compileAttributes
(或类似的东西(。因此,您不能使用此。解决此问题的一种方法是创建一个类似于此处的自定义构建脚本。删除了Rcpp::compileAttributes
创建的RcppExports.cpp
文件后,它实际上调用R CMD INSTALL
。我也喜欢通过调用devtools::test()
来运行测试,但是如果您愿意,可以删除此测试。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么在这个代码结束循环中没有得到结束
- R 包中的 TMB c++ 代码和 CRAN 检查
- 在R软件包中包含TMB C 代码的指南