![]() |
1
5
这是一个 rcpp 方法。
这比转置结果的内存效率高出约10倍
内存节省似乎稳定在减少5倍左右,或多或少是结果矩阵本身的分配。
或者,我们可以更接近R,并使用R循环来制作手册
是比换位规则好一点
请注意,如果你真的内存不足,你可以更改Rcpp函数直接修改输入,这意味着你不必分配另一个矩阵。否则,你最好在Rcpp中实现穆迪的聪明解决方案,因为它会更快,只需要分配输出矩阵。 |
![]() |
2
4
由于滚动求和可以被视为求和的减法,我们可以使用该包 {MatrixStats} 这能快速完成这些繁琐的任务。
由于转置成本高昂,你无法做到的事情:
具有 {MatrixStats}
|
![]() |
3
3
使用基R矩阵索引,我们可以
无需转置,以及
|
![]() |
4
3
按列或行滚动求和
|
expr | min | lq | 意思是 | 中值的 | uq | 最大值 | 奈瓦尔 | cld |
---|---|---|---|---|---|---|---|---|
matrix_rollsum | 9.128677 | 10.38814 | 15.78466 | 13.43251 | 17.54006 | 71.10719 | 1000 | 一 |
rcpp_column_roll | 23.195918 | 26.54276 | 33.65227 | 30.43353 | 38.11125 | 113.20687 | 1000 | b |
apply_rollsum | 58.027111 | 72.66437 | 87.12061 | 80.50741 | 94.53146 | 255.69353 | 1000 | c |
for_loop | 56.408078 | 71.78122 | 85.21565 | 79.10471 | 89.47916 | 269.55304 | 1000 | c |
row_roll_sum | 8.309067 | 10.40819 | 15.62686 | 12.93160 | 17.21942 | 81.76514 | 1000 | 一 |
res2 <- bench::mark(
matrix_rollsum = matrix_rollsum(mat_lg, 3,1),
rcpp_colum_roll = rcpp_column_roll(mat_lg,3),
apply_rollsum = apply_rollsum(mat_lg,3),
for_loop = for_loop(mat_lg,3),
row_roll_sum = row_roll_sum(mat_lg,width = 3),
iterations = 1000
)
summary(res2)[,1:9]
# A tibble: 5 x 6
expression min median `itr/sec` mem_alloc `gc/sec`
<bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
1 matrix_rollsum 9.11ms 11.1ms 79.7 15.31MB 29.0
2 rcpp_colum_roll 23.2ms 28.6ms 32.2 7.63MB 3.74
3 apply_rollsum 53.94ms 67.1ms 13.7 52.18MB 188.
4 for_loop 55.18ms 69ms 13.2 33.13MB 17.8
5 row_roll_sum 8.28ms 10.5ms 78.3 22.87MB 51.5
p1 <- ggplot2::autoplot(res1)
p2 <- ggplot2::autoplot(res2)
library(patchwork)
p1/p2
科尔提出了一个很好的观点。为什么要复制大矩阵?处理原始对象不会占用更少的内存吗?所以我重写了
Rcpp
函数使用原始对象。
#include <Rcpp.h>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
Rcpp::NumericMatrix test(NumericMatrix x, int n, int margin) {
Rcpp::NumericMatrix result(x.nrow(),x.ncol());
std::fill( result.begin(), result.end(), NumericVector::get_na() ) ;
double s=0.0;
if(margin==1){
for(int i = 0; i < x.nrow(); ++i){
for(int j = 0; j < x.ncol()-n+1;++j){
for(int q=j; q<j+n;q++){
s+=x(i,q);
}
result(i,j+n-1) = s;
s = 0.0;
}}}
if(margin==2){
for(int i = 0; i < x.ncol(); ++i){
for(int j = 0; j < x.nrow()-n+1;++j){
for(int q=j; q<j+n;q++){
s+=x(i,q);
}
result(j+n-1,i) = s;
s = 0.0;
}}}
return result;
}
正如科尔所怀疑的那样,新函数分配了原始函数一半的内存,但令人惊讶的是,它慢了3倍。
expr | min | lq | 意思是 | 中值的 | uq | 最大值 | 奈瓦尔 | cld |
---|---|---|---|---|---|---|---|---|
matrix_rollsum | 9.317332 | 10.84904 | 15.47414 | 13.75330 | 16.36336 | 101.6147 | 1000 | 一 |
测试 | 34.498511 | 40.08057 | 47.49839 | 43.26564 | 48.34093 | 211.3246 | 1000 | b |
# A tibble: 2 x 6
expression min median `itr/sec` mem_alloc `gc/sec`
<bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
1 matrix_rollsum 9.15ms 10.1ms 93.7 15.31MB 33.4
2 test 34.1ms 35.4ms 27.5 7.63MB 3.93
![]() |
5
1
也许,你可以尝试使用
但是,请注意,这将以列顺序格式为您提供输出。例如,
|
![]() |
6
1
这里提供的两个答案都同样好。对于你是在寻找列或行的滚动求和,还是你的输出应该通过设计进行转置,这个问题似乎有点混乱。如果你在寻找后者,我建议你查看科尔的答案,并反转输出矩阵的维度和索引。
也就是说,如果你要找的是列式操作和输出,你可以简单地使用
我相信
|
![]() |
7
0
这是一个基本的R选项,使用
或
|
![]() |
Moccar · 无NumPy的线性方程 7 年前 |
![]() |
JuMoGar · 如何在RHS上用二维矩阵求解线性方程组 7 年前 |
![]() |
blue-sky · 修改神经网络对单个样本进行分类 7 年前 |
![]() |
enanone · BLAS矩阵逐矩阵转置乘法 7 年前 |