gpt4 book ai didi

与 Stan 一起使用时 Rcpp 函数未定义

转载 作者:行者123 更新时间:2023-12-04 12:05:06 24 4
gpt4 key购买 nike

我有一个 R 包,它使用 Rcpp 来实现一些内部功能。这些函数不会导出供用户直接访问(请参阅 rcpptest 存储库中的最小可重现示例)。

我现在正尝试将 Stan 代码添加到 src/ 目录,以便在安装包时进行编译(rcppstan 存储库中的可重现示例)。但是,当我修改包以使用 Stan 时,我在 R CMD CHECK 中收到以下错误:

#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC

事实上,当我尝试调用使用 meanC 函数的 R 函数时,我收到一条错误消息:Error in meanC(x) : object '_rcppstan_meanC' not found.

据我所知,这是当我修改包以使用 rstan 时发生的变化,以及可能的原因。

  1. 仅使用Rcpp时,src/RcppExports.cpp中如下:

    static const R_CallMethodDef CallEntries[] = {
    {"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1},
    {NULL, NULL, 0}
    };

    RcppExport void R_init_rcpptest(DllInfo *dll) {
    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
    R_useDynamicSymbols(dll, FALSE);
    }
  2. 合并 Stan 后,该代码不再生成在 src/RcppExports.cpp 文件中。相反,这似乎是由 rstantools 包创建的 src/init.cpp 文件处理的。该文件的相关 block 在这里:

    static const R_CallMethodDef CallEntries[] = {
    {NULL, NULL, 0}
    };

    void attribute_visible R_init_rcppstan(DllInfo *dll) {
    // next line is necessary to avoid a NOTE from R CMD check
    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
    R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work
    }

为什么 src/init.cpp 中的代码使 Rcpp 函数未定义?相反,有没有一种方法可以编辑 src/init.cpp 以便 Stan 模型能够正确编译和访问,同时仍然允许 Rcpp要定义的功能?

最佳答案

init.cpp 负责注册方法,Makevars 禁止编译 cpp 文件。通过在 Makevars(和 Makevars.win)中进行以下更改,我可以编译它:

diff --git a/src/Makevars b/src/Makevars
index 7aedc5b..3ea312e 100644
--- a/src/Makevars
+++ b/src/Makevars
@@ -1,8 +1,9 @@
STANHEADERS_SRC = `"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" --vanilla -e "cat(system.file('include', 'src', package = 'StanHeaders'))"`
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error

-SOURCES = $(wildcard stan_files/*.stan)
-OBJECTS = $(SOURCES:.stan=.o) init.o
+CPP_SOURCES = $(wildcard *.cpp)
+STAN_SOURCES = $(wildcard stan_files/*.stan)
+OBJECTS = $(STAN_SOURCES:.stan=.o) $(CPP_SOURCES:.cpp=.o)

all: $(SHLIB)
@if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi

在调用 Rcpp::compileAttributes() 之后,方法注册再次出现在 RcppExports.cpp 中。当我尝试 R CMD INSTALL 时,我收到来自 .onLoad() 的错误,c.f. https://github.com/stan-dev/rstanarm/issues/190 .使用那里的解决方法,即 R CMD INSTALL --preclean 首先解决了这个问题,但并不可靠。对我来说解决问题的是改变

R_useDynamicSymbols(dll, FALSE);

进入

R_useDynamicSymbols(dll, TRUE);

RcppExports.cpp 中。这当然是有问题的,因为该文件可能会被覆盖,特别是在使用 RStudio/devtools 时。一个相当 hacky 的解决方案是添加

RcppExports.o: patch

patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp

.phony: all clean patch

Makevars(.win) 中。但最终问题似乎是 Rcpp 模块的 C++ 代码是在包安装期间在 src 的子目录中生成的。因此 Rcpp::compileAttributes() 不能在注册方法列表中包含相应的方法。我没有看到一个好的解决方案。现在包构建、检查和安装有两个注意事项:

N  checking installed package size
installed size is 7.8Mb
sub-directories of 1Mb or more:
libs 7.7Mb
N checking for GNU extensions in Makefiles
GNU make is a SystemRequirements.

关于与 Stan 一起使用时 Rcpp 函数未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50686623/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com