【问题标题】:Rcpp: extract subset of matrix using indexmatrixRcpp:使用 indexmatrix 提取矩阵的子集
【发布时间】:2016-04-30 19:45:52
【问题描述】:

我有一个关于从矩阵到向量的子集的问题。用户可以明确地给出索引矩阵(它是一个与 M 大小相同的矩阵,如果不需要条目,则为 0,如果必须提取条目,则为 1)。如果提供了 indexmatrix,那么我们只是将其子集化,如果没有提供 indexmatrix(indexmatrix = NULL),那么我们使用 type1(取 true 或 false)构建它。只有两种类型的索引矩阵是可能的。

我使用了 Subset of a Rcpp Matrix that matches a logical statement

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;

// [[Rcpp::export]]
arma::colvec extractElementsRcpp(arma::mat M, 
         Rcpp::Nullable<Rcpp::NumericMatrix> indexmatrix = R_NilValue,
         bool type1 = false) {

  unsigned int D = M.n_rows;  // dimension of the data
  arma::mat indmatrix(D, D);  // initialize indexmatrix

  if (indexmatrix.isNotNull()) {
     // copy indexmatrix to numericmatrix
     Rcpp::NumericMatrix indexmatrixt(indexmatrix);
     // make indexmatrix into arma matrix indmatrix  
     indmatrix = Rcpp::as<arma::mat>(indexmatrixt);  
  } //else {
    // get indexmatrix
 //   Rcpp::NumericMatrix indexmatrixt = getindexmatrix(D, type1)["indexmatrix"]; 
 //   // make indexmatrix into arma matrix
 //   indmatrix = Rcpp::as<arma::mat>(indexmatrixt);  
 // }

  arma::colvec unM = M.elem(find(indmatrix == 1)); // extract wanted elements

  return(unM);
}

效果很好,太好了!然而,速度并不是我所希望的。每当提供 indexmatrix 时,C++ 代码都会比普通的 R 代码慢,而我的目标是在速度上有一个很好的改进。我觉得我在复制矩阵太多了。但我是 C++ 新手,还没有找到避免它的方法。

速度对比如下:

                                test replications elapsed relative
2 extractElementsR(M, indexmatrix = ind)      100   0.084     1.00
1 extractElementsRcpp(M, indexmatrix = ind)   100   0.142     1.69

编辑:R函数定义为

extractElementsR <- function (M, indexmatrix, type1 = FALSE) {
  D <- nrow(M)

#  # get indexmatrix, if necessary
#  if(is.null(indexmatrix)) indexmatrix <- getindexmatrix(D, type1 = type1)$indexmatrix

  # extract wanted elements
  return (M[which(indexmatrix > 0)])
}

例如可以采用矩阵

M <- matrix(rnorm(1000^2), ncol = 1000)
indexmatrix <- matrix(1, 1000, 1000)
indexmatrix[lower.tri(indexmatrix)] <- 0

作为 M 和索引矩阵。

EDIT2:我在 Rcpp 函数中注释了 else 语句并省略了 R 函数中的默认 NULL 值,因为它对我的问题并不重要。我想在提供 indexmatrix 时提高 Rcpp 函数的速度。但是,我想保留默认的NULL 值(并在必要时创建和索引矩阵)。

【问题讨论】:

  • 什么是getindexmatrix
  • 它是一个构造索引矩阵的函数,根据维度和类型,如果没有索引矩阵传递给函数extractElementsR(cpp)。它的细节在这里并不重要,因为我想专注于在传递索引矩阵时提高速度,同时我希望函数保持索引矩阵的默认值为 NULL。
  • 当 type1 = T; 时,您可以将函数 getindexmatrix 视为构造索引矩阵的函数,如示例矩阵中提供的那样。当 type1 = F 时为 1-indexmatrix。当然与 M 具有相同的维度。
  • 实际上它很重要,因为没有它你的代码就无法运行。此外,这可能是导致extractElementsRcpp 性能缓慢的另一个因素。请包含此功能,因为您的示例目前无法重现。
  • 我明确提到我在提供 indexmatrix 时进行了基准测试,因此这部分代码永远不会运行,它对性能没有贡献。您可以在extractElementsRcpp 中注释else 部分并在R 代码中省略NULL 默认值而不改变意图。

标签: r performance subset default-value rcpp


【解决方案1】:

你能不能展示一下

  1. 函数extractElementR()
  2. 示例数据,以使其成为可重现示例?

乍一看,您正在混合 Rcpp 和 RcppArmadillo 类型以便与后者进行子集化。这将创建大量副本。我们现在可以同时使用 Rcpp(Kevin 在这里有一些答案)和 RcppArmadillo(几个较旧的答案)进行索引,因此您甚至可以尝试两种不同的方式。

【讨论】:

  • 问题中添加了 R 函数以及一个简单的数据示例。我试图寻找有关如何减少副本数量的答案,但似乎我找错地方了。
  • 感谢您完成问题。我现在正忙于其他事情,但也许其他人可以从这里拿走它。一层额外的副本来自您在 Armadillo 和 Rcpp 类型之间的切换,即使在函数界面中也是如此。也许简化并尝试不使用 Nullable 而是使用 arma 索引矩阵。降低代码复杂度。
  • 没问题。我想将函数中的 Null 默认值保留为索引矩阵,这在从 arma 索引矩阵开始时是不可能的。我尝试在 Rcpp 中做所有事情,这样可以避免大量复制,但无法让子集工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-14
  • 2015-09-04
相关资源
最近更新 更多