简体   繁体   English

如何避免在Rcpp函数中从R环境读取数据

[英]How to avoid reading data from R environment within Rcpp function

Even though MyCppFunction(NumericVector x) returns the desired output, I am not sure of a proper/efficient way to avoid reading the data on variable myY withou passing it as a function argument. 即使MyCppFunction(NumericVector x)返回所需的输出,我也不确定是否有适当/有效的方法来避免在不将变量myY作为函数参数传递的情况下读取数据。

The reason I do not pass the data as an argument is that I will eventually pass the C++ function as an objective function to minimize and the minimization routine accepts a function of one argument only, namely myX . 我没有将数据作为参数传递的原因是,我最终会将C ++函数作为目标函数传递以最小化,并且最小化例程仅接受一个参数的函数,即myX Just as an example: in R, I would pass myY to optim(...) in the following way : optim(par,fn=MyRFunction,y=myY) . 举个例子:在R中,我将通过以下方式将myY传递给optim(...)optim(par,fn=MyRFunction,y=myY)

Any advice on how to properly access myY from within the C++ function is appreciated, here's a minimal example of what I am afraid is a really wrong way to do it: 任何有关如何从C ++函数中正确访问myY建议都myY赞赏,这里有一个最小的例子,我担心这是一个错误的方法:

Update : I've modified the code to better reflect the context as well as what has been proposed in the answers. 更新 :我已经修改了代码以更好地反映上下文以及答案中提出的内容。 Just in case, the focus of my question lies on this line : NumericVector y = env["myY"]; // How to avoid this? 以防万一,我的问题的重点在这条线上: NumericVector y = env["myY"]; // How to avoid this? NumericVector y = env["myY"]; // How to avoid this?

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double MyCppFunction(NumericVector x) {

  Environment env = Environment::global_env();
  NumericVector y = env["myY"];  // How to avoid this?

  double res = 0;

  for (int i = 0; i < x.size(); i++) res = res + (x(i) * y(i));

  return res;
}

double MyCppFunctionNoExport(NumericVector x) {

  Environment env = Environment::global_env();
  NumericVector y = env["myY"];  // How to avoid this?

  double res = 0;

  for (int i = 0; i < x.size(); i++) res = res + (x(i) * y(i));

  return res;
}

// [[Rcpp::export]]
double MyCppFunction2(NumericVector x, NumericVector y) {
  double res = 0;

  for (int i = 0; i < x.size(); i++) res = res + (x(i) * y(i));

  return res;
}

// [[Rcpp::export]]
double MyRoutine(NumericVector x, Function fn) {

  for (int i = 0; i < x.size(); i++) fn(x);

  return 0;
}

// [[Rcpp::export]]
double MyRoutineNoExport(NumericVector x) {

  for (int i = 0; i < x.size(); i++) MyCppFunctionNoExport(x);

  return 0;
}

/*** R
MyRFunction <- function(x, y=myY) {
  res = 0
  for(i in 1:length(x)) res = res + (x[i]*y[i])
  return (res)
}

callMyCppFunction2 <- function(x) {
   MyCppFunction2(x, myY)
}

set.seed(123456)

myY = rnorm(1e3)
myX = rnorm(1e3)

all.equal(MyCppFunction(myX), MyRFunction(myX), callMyCppFunction2(myX))

require(rbenchmark)

benchmark(MyRoutine(myX, fn=MyCppFunction),
          MyRoutine(myX, fn=MyRFunction),
          MyRoutine(myX, fn=callMyCppFunction2),
          MyRoutineNoExport(myX), order="relative")[, 1:4]

*/

Output : 输出

 $ Rscript -e 'Rcpp::sourceCpp("stack.cpp")' > MyRFunction <- function(x, y = myY) { + res = 0 + for (i in 1:length(x)) res = res + (x[i] * y[i]) + return(res) + } > callMyCppFunction2 <- function(x) { + MyCppFunction2(x, myY) + } > set.seed(123456) > myY = rnorm(1000) > myX = rnorm(1000) > all.equal(MyCppFunction(myX), MyRFunction(myX), callMyCppFunction2(myX)) [1] TRUE > require(rbenchmark) Loading required package: rbenchmark > benchmark(MyRoutine(myX, fn = MyCppFunction), MyRoutine(myX, + fn = MyRFunction), MyRoutine(myX, fn = callMyCppFunction2), + MyRoutineNoEx .... [TRUNCATED] test replications elapsed relative 4 MyRoutineNoExport(myX) 100 1.692 1.000 1 MyRoutine(myX, fn = MyCppFunction) 100 3.047 1.801 3 MyRoutine(myX, fn = callMyCppFunction2) 100 3.454 2.041 2 MyRoutine(myX, fn = MyRFunction) 100 8.277 4.892 

Use two parameters and wrap the C++ function in an R function. 使用两个参数并将C ++函数包装在R函数中。

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double MyCppFunction(NumericVector x, NumericVector y) {
  return (sum(x) + sum(y));
}

R side: R面:

callMyCFunc <- function(x) {
   MyCppFunction(x, myY)
}

optim does allow one to pass additional variables. optim确实允许传递其他变量。 Here we minimize f over x and pass in the additional variable a . 在这里,我们将x f最小化并传递附加变量a

f <- function(x, a) sum((x - a)^2)
optim(1:2, f, a = 1)

giving: 给予:

$par
[1] 1.0000030 0.9999351

$value
[1] 4.22133e-09

$counts
function gradient 
      63       NA 

$convergence
[1] 0

$message
NULL

Another solution. 另一个解决方案。 Set global in C space: 在C空间中设置全局:

#include <Rcpp.h>
using namespace Rcpp;

static NumericVector yglobal;

// [[Rcpp::export]]
void set_Y(NumericVector y) {
  yglobal = y;
}

// [[Rcpp::export]]
double MyCppFunction(NumericVector x) {
  double res = 0;
  for (int i = 0; i < x.size(); i++) res = res + (x(i) * yglobal(i));
  return res;
}

R side: R面:

set.seed(123456)

myY = rnorm(1000)
set_Y(myY);
myX = rnorm(1000)

MyCppFunction(myX)

(Note: the purpose of static is to limit the scope of the variable to your particular script) (注意: static的目的是将变量的范围限制为您的特定脚本)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM