Даже если MyCppFunction(NumericVector x)
возвращает желаемый результат, я не уверен в правильном / эффективном способе избежать чтения данных в переменной myY
без передачи ее в качестве аргумента функции.
Причина, по которой яне передавайте данные в качестве аргумента, так как в конечном итоге я передам функцию C ++ в качестве целевой функции для минимизации, а подпрограмма минимизации принимает функцию только с одним аргументом, а именно myX
. Просто в качестве примера: в R я бы передал myY
на optim(...)
следующим образом: optim(par,fn=MyRFunction,y=myY)
.
Любой совет о том, как правильно получить доступ к myY
изв C ++ функция приветствуется, вот минимальный пример того, что я боюсь, что это действительно неправильный способ сделать это:
Обновление : я изменил код, чтобы лучше отражать контекста также то, что было предложено в ответах.На всякий случай, фокус моего вопроса лежит на этой строке: 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]
*/
Вывод :
$ 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