创建RcppArmadillo矩阵列表

时间:2016-08-08 19:33:16

标签: r rcpp

在MCMC算法的深处,我需要将用户提供的矩阵列表与向量相乘,即,每个MCMC迭代多次调用下面的Rcpp和RcppArmadillo代码:

List mat_vec1 (const List& Mats, const vec& y) {
    int n_list = Mats.size();
    Rcpp::List out(n_list);
    for (int i = 0; i < n_list; ++i) {
        out[i] = as<mat>(Mats[i]) * y;
    }
    return(out);
}

用户提供的列表Mats在MCMC期间保持不变,每次迭代中的向量y都会发生变化。效率是至关重要的,我试图看看我是否可以通过多次将Mats的元素转换为arma :: mat来加速代码(它只需要执行一次)。我尝试了以下方法

List arma_Mats (const List& Mats) {
    int n_list = Mats.size();
    Rcpp::List res(n_list);
    for (int i = 0; i < n_list; ++i) {
        res[i] = as<mat>(Mats[i]);
    }
    return(res);
}

然后

List mat_vec2 (const List& Mats, const vec& y) {
    int n_list = Mats.size();
    Rcpp::List aMats = arma_Mats(Mats);
    Rcpp::List out(n_list);
    for (int i = 0; i < n_list; ++i) {
        out[i] = aMats[i] * y;
    }
    return(out);
}

但这似乎不起作用。任何替代/更好解决方案的指针都非常受欢迎。

1 个答案:

答案 0 :(得分:3)

好的,我基本上在评论中写了答案,但后来我发现我们已经在RcppArmadillo.package.skeleton()创建的存根中提供了一个工作示例:

// [[Rcpp::export]]
Rcpp::List rcpparma_bothproducts(const arma::colvec & x) {
    arma::mat op = x * x.t();
    double    ip = arma::as_scalar(x.t() * x);
    return Rcpp::List::create(Rcpp::Named("outer")=op,
                              Rcpp::Named("inner")=ip);
}

这将返回给定向量的外积(矩阵)和内积(标量)的列表。

至于什么是快速的,什么不是:我建议不要猜测,而是 profile 并尽可能多地测量。我倾向于在Armadillo中做更多(独立的)C ++代码,并且最后只返回最小化转换。