我有两个矩阵:
setContentView(R.layout.splash2);
和向量matr1 = [k ; n]
matr2 = [n ; m]
。 x
向量length(x) = k
包含值x
1 : m
我必须执行以下操作,我使用n = 5
m = 3
k = m * n
matr1 <- matrix(sample(seq(0,1, by = 0.1), size = k * n, replace = T), nrow = k, ncol = n )
matr2 <- matrix(sample(seq(0,1, by = 0.1), size = m * n, replace = T), nrow = n, ncol = m)
x <- sample(1:m, size = k, replace = T)
循环解决了这个问题。
for
有没有办法以某种方式进行矢量化?
或者可能会使用一些技巧来加快计算速度?
P.S。我考虑过使用基本的并行化,但我想找到更聪明的方法
答案 0 :(得分:2)
我想了一会儿,但是:
foo <- apply(matr2,2,function(x) rev(cumprod(x+1)))
matr3 <- matr1*t(foo[,x])
- 证明 -
set.seed(100)
n = 5
m = 3
k = m * n
matr1 <- matrix(sample(seq(0,1, by = 0.1), size = k * n, replace = T), nrow = k, ncol = n )
matr2 <- matrix(sample(seq(0,1, by = 0.1), size = m * n, replace = T), nrow = n, ncol = m)
x <- sample(1:m, size = k, replace = T)
foo <- apply(matr2,2,function(x) rev(cumprod(x+1)))
matr3 <- matr1*t(foo[,x])
for( i in 1:k){
for( j in 1:n){
matr1[i, 1:(n-j+1)] <- matr1[i, 1:(n-j+1)] +
matr1[i, 1:(n-j+1)] * matr2[j , x[i]]
}
}
all.equal(matr3,matr1)
# TRUE
- 说明 -
所以我花了一段时间才弄清楚这一点,但是这里......假设你的代码并假设i = 1
,我们基本上可以写j=1
:
matr1[1,1:5] <- matr1[1,1:5] + matr1[1,1:5] * matr2[1,3]
所以你把第1行,第1列到第5列,然后用原始数字加上这些数字加上那些数字乘以其他数字(在这种情况下为0.8
)。然后,当j=2
:
matr1[1,1:4] <- matr1[1,1:4] + matr1[1,1:4] * matr2[2,3]
所以现在你只接受n
本身的所有列,并以与步骤1相同的方式更新值。最后,应该明确的模式是更新matr1[1,1]
{ {1}}次,n
时间更新matr[1,n]
次(仅1
次。
我们通过一次性预先计算所有步骤来利用此模式。我们这样做:
matr2[1,3]
这基本上是一个新表,对于每列foo <- apply(matr2,2,function(x) rev(cumprod(x+1)))
,包含一个数字。此数字是您之前的代码遇到单个数字的所有循环的组合。因此,我们现在只需执行1次,而不是matr1[i,]
需要5次乘法。
现在我们有:
matr1[1,1]
我们可以将其减少到:
for (i in 1:k) for (j in 1:n) matr1[i,j] <- matr1[i,j] * foo[j,x[i]]
由于for (i in 1:k) matr1[i,] <- matr1[i,] * foo[,x[i]]
每次都为i
索引,因此我们只能对其进行矢量化:
1:k
我们已经完成了。
- 基准 -
我重新考虑了我作为证据提供的代码块,但使用了matr <- matr*t(foo[,x])
和n=100
。
您的代码:
m=100
我的代码:
# user system elapsed
# 6.85 0.00 6.86
答案 1 :(得分:0)
而不是双循环,你可以在k-n-grid上apply
。
suppressOutput <- apply(expand.grid(1:k, 1:n), 1, function(y){
matr1[y[1], 1:(n-y[2]+1)] <<- matr1[y[1], 1:(n-y[2]+1)] + matr1[y[1], 1:(n-y[2]+1)] * matr2[y[2] , x[y[1]]]
})
在我的机器上节省超过50%的计算时间。虽然它不是很漂亮。