考虑A和B是两个尺寸为10 ^ 8 X 5的高密度矩阵。 即;
rowSums(A * B)
我想计算A的每一行的点积与B的相应行,即
{{1}}
但它很慢,我想知道是否有更快的方法。
答案 0 :(得分:2)
这可能让你失望,但在R级别,这已经是你自己不用编写一些C代码就能获得的最好成绩。问题在于,通过rowSums(A * B)
,您实际上正在做
C <- A * B
rowSums(C)
第一行执行三个大型高薄矩阵的全扫描;而第二行执行1个大型高薄矩阵的全扫描。总而言之,我们等效地扫描了4倍高密度矩阵(内存密集型)。
事实上,对于此类操作,最佳算法只需要扫描n * p
高 - 薄矩阵两次,方法是 rowwise cross product :
rowsum <- numeric(n)
for j = 1, 2, ... p
rowsum += A[,i] * B[,i]
通过这种方式,我们也避免生成矩阵C
。注意,上面只是一个假代码,而不是有效的R代码甚至是C代码。但这个想法很清楚,我们想用C编写这个。
与您的情况类比的是sum(x * y)
和crossprod(x, y)
之间的速度差异,假设x
和y
是相同长度的大型向量。
x <- runif(1e+7)
y <- runif(1e+7)
system.time(sum(x * y))
# user system elapsed
# 0.124 0.032 0.158
system.time(crossprod(x, y))
# user system elapsed
# 0.036 0.000 0.056
在第一种情况下,我们扫描长矢量4次,而在第二种情况下,我们只扫描它两次。
统计计算的相关性
rowSums(A * B)
实际上是diag(tcrossprod(A, B))
的有效评估,常见于与逐点预测方差相关的回归计算中。例如,在来自模型矩阵的QR因子分解的具有薄Q
矩阵的普通线性正方形回归中,拟合值的逐点方差是diag(tcrossprod(Q))
,其由rowSums(Q ^ 2)
更有效地计算。但是,由于已经解释过的原因,这仍然不是最快的评估。