在循环中调用 Rcpp 函数时 R 崩溃
R crashes when calling a Rcpp function in a loop
所以我在 .cpp
文件中有这个 Rcpp 函数。您会看到它正在调用其他自定义函数,为简单起见我没有显示这些函数,但这些函数没有显示任何问题。
// [[Rcpp::export]]
int sim_probability(float present_wealth , int time_left, int n, float mu, float sigma, float r, float gamma, float gu, float gl){
int i;
int count = 0;
float final_wealth;
NumericVector y(time_left);
NumericVector rw(time_left);
for(i=0;i<n;i++){
rw = random_walk(time_left, 0);
y = Y(rw, mu, sigma, r, gamma);
final_wealth = y[time_left-1] - y[0] + present_wealth;
if(final_wealth <= gu && final_wealth >= gl){
count = count + 1;
}
}
return count;
}
然后我可以从 .R
无缝地调用这个函数:
library(Rcpp)
sourceCpp("functions.cpp")
sim_probability(present_wealth = 100, time_left = 10, n = 1e3, mu = 0.05, sigma = 0.20, r = 0, gamma = 2, gu = 200, gl = 90)
但是,如果我在 for
循环中调用它,无论它有多小,R 都会崩溃而不会弹出任何明显的错误。下面的块会使 R 崩溃。
for(l in 1:1){
sim_probability(present_wealth = 100, time_left = 10, n = 1e3, mu = 0.05, sigma = 0.20, r = 0, gamma = 2, gu = 200, gl = 90)
}
我也试过尽可能快地手动执行 (Ctrl + Enter) 多次,但我的速度足够快,它也崩溃了。
我在函数外和函数内尝试过更小或更大的循环。如果从另一个 Rcpp 函数调用它,它也会崩溃。我知道我不应该在 R 循环中调用 Rcpp 函数。最后我打算从另一个 Rcpp 函数调用它(生成数据矩阵)但它还是崩溃了。
我跟踪了其他案例,我发现谷歌搜索并尝试了一些事情,如更改为数组索引的 []
括号 (), playing with the gc()
garbage collector (as suggested here).
我怀疑 NumericVector
定义出了问题。但据我所知,它们已正确声明。
评论中已经明确指出这不是一个可重现的例子。我将在此处添加缺少的函数 Y()
和 random_walk()
:
// [[Rcpp::export]]
NumericVector Y(NumericVector path, float mu, float sigma, float r, float gamma){
int time_step, n, i;
time_step = 1;
float theta, y0, prev, inc_W;
theta = (mu - r) / sigma;
y0 = theta / (sigma*gamma);
n = path.size();
NumericVector output(n);
for(i=0;i<n;i++){
if(i == 0){
prev = y0;
inc_W = path[0];
}else{
prev = output[i-1];
inc_W = path[i] - path[i-1];
}
output[i] = prev + (theta / gamma) * (theta * time_step + inc_W);
}
return output;
}
// [[Rcpp::export]]
NumericVector random_walk(int length, float starting_point){
if(length == 1){return starting_point;}
NumericVector output(length);
output[1] = starting_point;
int i;
for(i=0; i<length; i++){output[i+1] = output[i] + R::rnorm(0,1);}
return output;
}
编辑 1:添加了更多代码以使其可重现。
Edit2:我在调用函数时分配局部变量。这对我来说是愚蠢的,但无害。同样的错误仍然存在。但我已经解决了。
Edit3:正如 Dirk 在评论中指出的那样,我正在做一个毫无意义的练习来重新定义 rnorm()
。现在它已被删除并修复。
答案已在评论中解决,@coatless。我把它放在这里是为了留给未来的读者。问题是 random_walk()
函数没有正确设置。
问题在于函数内的循环允许 i
超出向量 output
的定义维度。这只是 低效 调用一次,但它有效。但是当它被快速调用多次时它会爆炸。
所以为了避免这个错误和许多其他错误,该函数应该定义为
// [[Rcpp::export]]
NumericVector random_walk(int length, float starting_point){
if(length == 0){return starting_point;}
NumericVector output(length);
output[0] = starting_point;
int i;
for(i=0; i<length-1; i++){output[i+1] = output[i] + R::rnorm(0,1);}
return output;
}
所以我在 .cpp
文件中有这个 Rcpp 函数。您会看到它正在调用其他自定义函数,为简单起见我没有显示这些函数,但这些函数没有显示任何问题。
// [[Rcpp::export]]
int sim_probability(float present_wealth , int time_left, int n, float mu, float sigma, float r, float gamma, float gu, float gl){
int i;
int count = 0;
float final_wealth;
NumericVector y(time_left);
NumericVector rw(time_left);
for(i=0;i<n;i++){
rw = random_walk(time_left, 0);
y = Y(rw, mu, sigma, r, gamma);
final_wealth = y[time_left-1] - y[0] + present_wealth;
if(final_wealth <= gu && final_wealth >= gl){
count = count + 1;
}
}
return count;
}
然后我可以从 .R
无缝地调用这个函数:
library(Rcpp)
sourceCpp("functions.cpp")
sim_probability(present_wealth = 100, time_left = 10, n = 1e3, mu = 0.05, sigma = 0.20, r = 0, gamma = 2, gu = 200, gl = 90)
但是,如果我在 for
循环中调用它,无论它有多小,R 都会崩溃而不会弹出任何明显的错误。下面的块会使 R 崩溃。
for(l in 1:1){
sim_probability(present_wealth = 100, time_left = 10, n = 1e3, mu = 0.05, sigma = 0.20, r = 0, gamma = 2, gu = 200, gl = 90)
}
我也试过尽可能快地手动执行 (Ctrl + Enter) 多次,但我的速度足够快,它也崩溃了。
我在函数外和函数内尝试过更小或更大的循环。如果从另一个 Rcpp 函数调用它,它也会崩溃。我知道我不应该在 R 循环中调用 Rcpp 函数。最后我打算从另一个 Rcpp 函数调用它(生成数据矩阵)但它还是崩溃了。
我跟踪了其他案例,我发现谷歌搜索并尝试了一些事情,如更改为数组索引的 []
括号 (gc()
garbage collector (as suggested here).
我怀疑 NumericVector
定义出了问题。但据我所知,它们已正确声明。
评论中已经明确指出这不是一个可重现的例子。我将在此处添加缺少的函数 Y()
和 random_walk()
:
// [[Rcpp::export]]
NumericVector Y(NumericVector path, float mu, float sigma, float r, float gamma){
int time_step, n, i;
time_step = 1;
float theta, y0, prev, inc_W;
theta = (mu - r) / sigma;
y0 = theta / (sigma*gamma);
n = path.size();
NumericVector output(n);
for(i=0;i<n;i++){
if(i == 0){
prev = y0;
inc_W = path[0];
}else{
prev = output[i-1];
inc_W = path[i] - path[i-1];
}
output[i] = prev + (theta / gamma) * (theta * time_step + inc_W);
}
return output;
}
// [[Rcpp::export]]
NumericVector random_walk(int length, float starting_point){
if(length == 1){return starting_point;}
NumericVector output(length);
output[1] = starting_point;
int i;
for(i=0; i<length; i++){output[i+1] = output[i] + R::rnorm(0,1);}
return output;
}
编辑 1:添加了更多代码以使其可重现。
Edit2:我在调用函数时分配局部变量。这对我来说是愚蠢的,但无害。同样的错误仍然存在。但我已经解决了。
Edit3:正如 Dirk 在评论中指出的那样,我正在做一个毫无意义的练习来重新定义 rnorm()
。现在它已被删除并修复。
答案已在评论中解决,@coatless。我把它放在这里是为了留给未来的读者。问题是 random_walk()
函数没有正确设置。
问题在于函数内的循环允许 i
超出向量 output
的定义维度。这只是 低效 调用一次,但它有效。但是当它被快速调用多次时它会爆炸。
所以为了避免这个错误和许多其他错误,该函数应该定义为
// [[Rcpp::export]]
NumericVector random_walk(int length, float starting_point){
if(length == 0){return starting_point;}
NumericVector output(length);
output[0] = starting_point;
int i;
for(i=0; i<length-1; i++){output[i+1] = output[i] + R::rnorm(0,1);}
return output;
}