它似乎并不像matrix
包采取andvantage对称性:
> n <- 100
> x <- s <- matrix(runif(n^2),n,n)
> s[lower.tri(s)] <- t(s)[lower.tri(s)]
>
> library(Matrix)
> s_sym <- Matrix(forceSymmetric(s))
> class(s_sym) # has the symmetric class
[1] "dsyMatrix"
attr(,"package")
[1] "Matrix"
>
> library(microbenchmark)
> microbenchmark(x %*% x, s %*% s, s_sym %*% s_sym)
Unit: microseconds
expr min lq mean median uq max neval
x %*% x 461 496 571 528 625 1008 100
s %*% s 461 499 560 532 572 986 100
s_sym %*% s_sym 553 568 667 624 701 1117 100
没有任何迹象表明,它应在帮助文件:
基本矩阵产品,%*%
实现我们所有的矩阵和 也为sparseVector
类,完全类似的r基地矩阵 和矢量对象。功能crossprod
和tcrossprod
是矩阵 产品或“交叉产品”,理想情况下有效实施,不需要 计算t(.)
。当易于检测时,例如,在crossprod(m)
, 一个参数情况下,它们也返回分类矩阵。 tcrossprod()
取矩阵的转置矩阵的交叉乘积。 tcrossprod(x)
正式相当于,但 快,呼吁x %*% t(x)
,所以tcrossprod(x, y)
而不是 x %*% t(y)
。
用于您的解决方案是让使用Rcpp
包装功能和R_ext/BLAS.h
提供的BLAS功能。你可以做到这一点,如下所示:做一个func.cpp
像这样的:
// added to get $(BLAS_LIBS) in compile flags
//[[Rcpp::depends(RcppArmadillo)]]
#include <Rcpp.h>
#include <R_ext/BLAS.h>
/*
Wrapper for BLAS dsymm. See dsymm http://www.netlib.org/lapack/explore-html/d1/d54/group__double__blas__level3_ga253c8edb8b21d1b5b1783725c2a6b692.html#ga253c8edb8b21d1b5b1783725c2a6b692
Only works with side = 'R'
Note intput is by refernce with &
*/
// [[Rcpp::export]]
Rcpp::NumericMatrix blas_dsymm(
char uplo, int m, int n, double alpha,
const Rcpp::NumericMatrix &A, const Rcpp::NumericMatrix &B){
// set lda, ldb and ldc
int lda = n, ldb = m, ldc = m;
// make new matrix with dim(m, n)
Rcpp::NumericMatrix C(m, n); // default values are zero
double beta = 0;
F77_NAME(dsymm)(
"R" /* side */, &uplo, &m, &n, &alpha,
A.begin(), &lda, B.begin(), &ldb, &beta, C.begin(), &ldc);
return(C);
}
然后运行下列R-脚本:
> n <- 100
> m <- 200
> s<-matrix(runif(n^2),n,n)
> s[lower.tri(s)] <- t(s)[lower.tri(s)]
> x <- matrix(runif(m*n), m, n)
>
> library("Rcpp")
> sourceCpp("func.cpp")
>
> out <- x %*% s
> out_blas <- blas_dsymm(
+ uplo = "U", m = nrow(x), n = ncol(x),
+ alpha = 1, A = s, B = x)
>
> all.equal(out, out_blas)
[1] TRUE
>
> library(microbenchmark)
> microbenchmark(
+ dense = x %*% s,
+ BLAS = blas_dsymm(
+ uplo = "U", m = nrow(x), n = ncol(x),
+ alpha = 1, A = s, B = x))
Unit: microseconds
expr min lq mean median uq max neval
dense 880.989 950.3225 1114.744 1066.866 1159.311 2783.213 100
BLAS 858.866 938.6680 1169.839 1016.495 1225.286 3261.633 100
它似乎并没有在这里做任何区别。请注意,您需要安装RcppArmadillo
和Rcpp
软件包。
也许在'Matrix'包里有什么?它有一个对称类。或者可能是'matrixStats'包。 – lmo