【发布时间】:2015-09-27 16:40:10
【问题描述】:
我需要计算一个LogicalMatrix 中所有TRUE 的行数。
因为我需要能够相对固定地执行 1 到 25 亿次,所以速度真的很重要:
我目前最好的:
我想出的最有效/最快的单进程方法是多少 Rcpp 函数 (hm2)。
我有限的分析能力表明,绝大多数时间都花在了if(r_tll == xcolls){... 上。我似乎想不出更快的不同算法(我已经尝试在找到FALSE 后立即跳出循环,但速度要慢得多)。
可以推测的细节:
我可以假设:
- 矩阵的行数总是少于 1000 万行。
- 来自上游的所有输出矩阵将具有相同数量的列(对于给定的会话/进程/线程)。
- 每个矩阵的列数永远不会超过 2326 个。
小例子:
m <- matrix(sample(c(T,F),50000*10, replace = T),ncol = 10L)
head(m)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] FALSE FALSE TRUE FALSE FALSE TRUE TRUE TRUE TRUE FALSE
#> [2,] FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE TRUE
#> [3,] FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE
#> [4,] TRUE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE
#> [5,] TRUE FALSE FALSE FALSE TRUE TRUE TRUE FALSE TRUE TRUE
#> [6,] FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
// [[Rcpp::export]]
int hm(const LogicalMatrix& x){
const int xrows = x.nrow();
const int xcols = x.ncol();
int n_all_true = 0;
for(size_t row = 0; row < xrows; row++) {
int r_ttl = 0;
for(size_t col = 0; col < xcols; col++) {
r_ttl += x(row,col);
}
if(r_ttl == xcols){
n_all_true++;
}
}
return n_all_true;
}
我不明白为什么,但在我的机器上,如果我烘焙的列数会更快(如果有人能解释为什么会这样,那就太好了):
// [[Rcpp::export]]
int hm2(const LogicalMatrix& x){
const int xrows = x.nrow();
// const int xcols = x.ncol();
int n_all_true = 0;
for(size_t row = 0; row < xrows; row++) {
int r_ttl = 0;
for(size_t col = 0; col < 10; col++) {
r_ttl += x(row,col);
}
if(r_ttl == 10){
n_all_true += 1;
}
}
return n_all_true;
}
时机:
microbenchmark(hm(m), hm2(m), times = 1000)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> hm(m) 597.828 599.0995 683.3482 605.397 643.8655 1659.711 1000
#> hm2(m) 236.847 237.6565 267.8787 238.748 253.5280 683.221 1000
【问题讨论】:
-
你试过多线程吗?
-
@JamesMoore 我可以将数据分派到不同的线程,根据输入数据计算逻辑矩阵,然后计算是的——但这是一个测试用例;需要为每个线程生成 100M 个矩阵)...基本上我们可以提出的问题的大小取决于我可以执行此步骤的效率(生成这样一个矩阵的 alg 大约快 100 倍),所以这是瓶颈.在梦境中,这将比我目前在单线程上的解决方案快 100 倍。感谢您的意见!
-
关于你为什么这个问题 - “如果我烘烤列数它会更快” - 是真的,很可能与这样一个事实有关,因为列数是一个编译时间常数,编译器可以将其纳入其优化策略。这在第一种情况下是不可能的(
hm函数),其中xcols必须在运行时确定。 -
如果您知道行数也是恒定的,那将节省更多时间。
标签: c++ r performance matrix rcpp