我注意到在R语言中,从右到左计算二次形式中的矩阵运算比从左到右更快,具体取决于括号的放置方式。显然,它们都执行了相同数量的计算。不知道这是为什么。这与内存分配有关吗?
# A: 5000 * 5000
# B: 5000 * 2
A = matrix(runif(5000 * 5000), nrow = 5000)
B = matrix(rbinom(5000 * 2, size = 2, prob = 0.3), nrow = 5000)
microbenchmark((t(B) %*% A) %*% B, t(B) %*% (A %*% B), times = 100)
下面是会话信息:
R version 4.2.0 (2022-04-22)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Big Sur 11.4
Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] Rcpp_1.0.9 microbenchmark_1.4.9
loaded via a namespace (and not attached):
[1] compiler_4.2.0 fastmap_1.1.0 cli_3.3.0 htmltools_0.5.3 tools_4.2.0
[6] RcppArmadillo_0.11.2.4.0 rstudioapi_0.13 yaml_2.3.5 rmarkdown_2.14 knitr_1.39
[11] xfun_0.31 digest_0.6.29 rlang_1.0.4 evaluate_0.15
编辑: 一个简化版本的矩阵乘法,显示相同的错误。
k <- 5000L; m <- n <- 2L;
A <- matrix(rnorm(k * k), k, k);
B <- matrix(rnorm(k * n), k, n);
tB <- t(B);
microbenchmark::microbenchmark(tB %*% A, A %*% B, times = 100)
sessionInfo()
吗?(我正在使用 openblas) - user20650crossprod()
/tcrossprod()
的相对时间。 - Ben Bolkermicrobenchmark(crossprod(B, A) %*% B, t(B) %*% (A %*% B), times = 100)
将第一个操作减少了一半,降至67毫秒,但仍然比第二个慢得可测。基本的R操作%*%
非常复杂,包含NA
和无限检查,并且在矩阵或向量很薄的情况下存在重大的开销潜力。也许这篇相关的文章会对您有所帮助:https://dev59.com/PFUK5IYBdhLWcg3w9zuJ - dcsukak <- 5000L; m <- n <- 2L; A <- matrix(rnorm(k * k), k, k); B <- matrix(rnorm(k * n), k, n); tB <- t(B); microbenchmark::microbenchmark(tB %*% A, A %*% B)
- Mikael Jagan