使累计总和更快

2024-04-06

我正在尝试计算矩阵每一列的累积和。这是我的 R 代码:

testMatrix = matrix(1:65536, ncol=256);
microbenchmark(apply(testMatrix, 2, cumsum), times=100L);

Unit: milliseconds
                         expr      min       lq     mean  median       uq      max neval
 apply(testMatrix, 2, cumsum) 1.599051 1.766112 2.329932 2.15326 2.221538 93.84911 10000

我使用Rcpp进行比较:

cppFunction('NumericMatrix apply_cumsum_col(NumericMatrix m) {
    for (int j = 0; j < m.ncol(); ++j) {
        for (int i = 1; i < m.nrow(); ++i) {
            m(i, j) += m(i - 1, j);
        }
    }
    return m;
}');
microbenchmark(apply_cumsum_col(testMatrix), times=10000L);

Unit: microseconds
                         expr     min      lq     mean  median      uq      max neval
 apply_cumsum_col(testMatrix) 205.833 257.719 309.9949 265.986 276.534 96398.93 10000

所以 C++ 代码的速度是原来的 7.5 倍。有可能做得比apply(testMatrix, 2, cumsum)在纯 R 中?感觉就像我无缘无故地有一个数量级的开销。


仅用 R 代码很难击败 C++。我能想到的最快方法是,如果您愿意将矩阵拆分为列表。这样,R 使用原始函数并且不会在每次迭代时复制对象(apply本质上是一个漂亮的循环)。您可以看到 C++ 仍然胜出,但速度有了显着提升list如果您真的只想使用 R 代码,请使用此方法。

fun1 <- function(){
    apply(testMatrix, 2, cumsum)
}

testList <- split(testMatrix, col(testMatrix))

fun2 <- function(){
    lapply(testList, cumsum)
}

microbenchmark(fun1(),
               fun2(),
               apply_cumsum_col(testMatrix),
               times=100L)


Unit: microseconds
                         expr      min        lq      mean   median        uq      max neval
                       fun1() 3298.534 3411.9910 4376.4544 3477.608 3699.2485 9249.919   100
                       fun2()  558.800  596.0605  766.2377  630.841  659.3015 5153.100   100
 apply_cumsum_col(testMatrix)  219.651  282.8570  576.9958  311.562  339.5680 4915.290   100

EDIT请注意,此方法比fun1如果您包括将矩阵拆分为列表的时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使累计总和更快 的相关文章

随机推荐