在循环中调用Rcpp函数时R崩溃

时间:2018-12-09 17:36:01

标签: c++ r rcpp

因此,我在.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函数调用它(以生成数据矩阵),但是它完全崩溃了。

我追踪了其他一些我发现使用谷歌搜索并尝试过一些事情的情况,例如将数组索引(this question)的括号改为[],并使用gc()垃圾收集器(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;
}

Edit1:添加了更多代码,因此可重复使用。

Edit2:调用函数时,我正在分配局部变量。从我的角度来看这是愚蠢的,但无害。相同的错误仍然存​​在。但是我已经解决了。

Edit3:正如Dirk在评论中指出的那样,我正在做一个毫无意义的练习,重新定义rnorm()。现在,将其删除并修复。

1 个答案:

答案 0 :(得分:0)

答案已经通过@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;
}