在Rcpp中从列表中提取元素似乎有点慢

在Rcpp中从列表中提取元素似乎有点慢,r,rcpp,R,Rcpp,我刚刚用三个大小相同的输入向量编写了一个Rcpp函数,x(数字)y(数字)和类别(字符)。然后我想返回一个列表,列表大小等于唯一类别值的长度。此列表中的每个元素都是基于具有相应类别的x和y的相同大小矩阵(相等的行和列) 然而,当n的大小很大时,我发现我的代码速度不够快。我想原因是我需要从列表中提取一些东西,做一些计算,然后每次都把它插回去。有没有人对如何加快这一进程提出建议 Rcpp代码 #include <Rcpp.h> using namespace Rcpp; //[[Rcp

我刚刚用三个大小相同的输入向量编写了一个Rcpp函数,
x
(数字)
y
(数字)和
类别
(字符)。然后我想返回一个列表,列表大小等于唯一类别值的长度。此列表中的每个元素都是基于具有相应类别的
x
y
的相同大小矩阵(相等的行和列)

然而,当
n
的大小很大时,我发现我的代码速度不够快。我想原因是我需要从列表中提取一些东西,做一些计算,然后每次都把它插回去。有没有人对如何加快这一进程提出建议

Rcpp代码

#include <Rcpp.h>
using namespace Rcpp;

//[[Rcpp::export]]
List myList(NumericVector x, NumericVector y, CharacterVector category) {

  int n = x.size();
  CharacterVector levels = unique(category);
  int levels_size = levels.size();
  List L(levels_size);

  int plot_width = 600;
  int plot_height = 600;

  // Each element in the list L has the same size Matrix
  for(int j = 0; j < levels_size; j++) {
    NumericMatrix R(plot_height, plot_width);
    L[j] = R;
  }
  int id = 0;

  double xmax = max(x);
  double ymax = max(y);
  double xmin = min(x);
  double ymin = min(y);

  for(int i=0; i < n; i++) {

    for(int j = 0; j < levels_size; j++) {
      if(category[i] == levels[j]) {
        id = j;
        break;
      }
    }

    int id_x = floor((x[i] - xmin)/(xmax - xmin) * (plot_width - 1));
    int id_y = floor((y[i] - ymin)/(ymax - ymin) * (plot_height - 1));

    NumericMatrix M = L[id];
    // some computation in M
    M(id_y, id_x) += 1;
    L[id] = M;
  }
  return(L);
}
n <- 1e8
class <- 20

x <- rnorm(n)
y <- rnorm(n)
category <- sample(as.factor(1:class), size = n, replace = TRUE)

start_time <- Sys.time()
L <- myList(x = x, y = y, category = category)
end_time <- Sys.time()
end_time - start_time
# Time difference of 35.3367 secs
#包括
使用名称空间Rcpp;
//[[Rcpp::导出]]
列表myList(数字向量x、数字向量y、字符向量类别){
int n=x.size();
CharacterVector级别=唯一(类别);
int levels_size=levels.size();
列表L(级别和大小);
int plot_width=600;
int plot_高度=600;
//列表L中的每个元素都有相同的大小矩阵
对于(int j=0;j
R代码

#include <Rcpp.h>
using namespace Rcpp;

//[[Rcpp::export]]
List myList(NumericVector x, NumericVector y, CharacterVector category) {

  int n = x.size();
  CharacterVector levels = unique(category);
  int levels_size = levels.size();
  List L(levels_size);

  int plot_width = 600;
  int plot_height = 600;

  // Each element in the list L has the same size Matrix
  for(int j = 0; j < levels_size; j++) {
    NumericMatrix R(plot_height, plot_width);
    L[j] = R;
  }
  int id = 0;

  double xmax = max(x);
  double ymax = max(y);
  double xmin = min(x);
  double ymin = min(y);

  for(int i=0; i < n; i++) {

    for(int j = 0; j < levels_size; j++) {
      if(category[i] == levels[j]) {
        id = j;
        break;
      }
    }

    int id_x = floor((x[i] - xmin)/(xmax - xmin) * (plot_width - 1));
    int id_y = floor((y[i] - ymin)/(ymax - ymin) * (plot_height - 1));

    NumericMatrix M = L[id];
    // some computation in M
    M(id_y, id_x) += 1;
    L[id] = M;
  }
  return(L);
}
n <- 1e8
class <- 20

x <- rnorm(n)
y <- rnorm(n)
category <- sample(as.factor(1:class), size = n, replace = TRUE)

start_time <- Sys.time()
L <- myList(x = x, y = y, category = category)
end_time <- Sys.time()
end_time - start_time
# Time difference of 35.3367 secs

n我怀疑性能方面存在两个主要问题:

  • 大量字符串比较(顺序为
    1e9
  • 矩阵的大量缓存未命中,因为通常两个连续的xy对不会来自同一类别,因此需要不同的矩阵
两者都指向同一个方向:不要试图实现自己的分组操作。数据库引擎和包,如
data.table
更了解如何做到这一点。例如,当使用
data.table
时,我们需要一个简单得多的函数,该函数期望x和y代表一个类别,并输出一个矩阵:

#包括
使用名称空间Rcpp;
//[[Rcpp::导出]]
数值矩阵getMat(数值向量x,数值向量y,
双xmin,双xmax,双ymin,双ymax,
int plot_宽度=600,int plot_高度=600){
int n=x.size();
数字矩阵M(绘图高度、绘图宽度);
对于(int i=0;in你试过什么?您会遇到哪些错误?``包括使用名称空间Rcpp;模板类ListOf:public List{public:template ListOf(const T&x):List(x){}什么操作符[](int i){返回为(((List*)this)->操作符[](i));};//[[Rcpp::export]]double-sacha(ListOf x){double-sum=0.0;用于(int i=0;使用名称空间Rcpp;
是危险的。
无论如何,
ListOf
同时也是Rcpp的一部分,因此您可以省略模板定义。不过,我不确定这是否有助于您的代码。您是对的!我可以删除模板定义,代码速度更快。但速度不如我想象的快。还有其他方法可以删除吗快一点?