在并行计算中更新相同的内存(矩阵)?
Updating the same memory (matrix) on parallel computations?
我有一个强大的用例来并行化 SGD 算法的一种风格。在这种用例中,我需要使用增量梯度更新和随机批次样本来更新矩阵 P 和 Q。每个进程将更新两个矩阵上互斥的索引。
我打算做的事情的简单说明如下:
# create "big" matrix
A <- matrix(rnorm(10000), 100, 100)
system.time(
# update each row vector independently using all my cores
r <- mclapply(1:100, mc.cores = 6, function(i) {
# updating ...
A[i,] <- A[i,] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(sum(A[i,]^2))
})
)
使用这种方法有什么缺点吗?是否有更多 R 惯用的替代品?
例如,为了干净(即没有副作用,不可变的计算)返回更新 A[i,] - 0.01
而不是 RMSE
会使编程更复杂并且内存使用达到峰值甚至 运行 内存不足。
使用包 {bigstatsr} 的共享数据按块重新实现您的代码:
N <- 10e3
A <- matrix(rnorm(N * N), N)
library(bigstatsr)
bigA <- as_FBM(A)
library(doParallel)
registerDoParallel(cl <- makeCluster(4))
system.time(
r <- foreach(i = seq_len(N), .combine = 'c') %dopar% {
# updating ...
A[i,] <- A[i,] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(sum(A[i,]^2))
}
) # 11 sec
stopCluster(cl)
registerDoParallel(cl <- makeCluster(4))
system.time(
r2 <- big_apply(bigA, function(X, ind) {
# updating ...
tmp <- bigA[ind, ] <- bigA[ind, ] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(rowSums(tmp^2))
}, a.combine = 'c')
) # 1 sec
stopCluster(cl)
all.equal(r, r2) # TRUE
同样,更新列而不是行会更好。
我有一个强大的用例来并行化 SGD 算法的一种风格。在这种用例中,我需要使用增量梯度更新和随机批次样本来更新矩阵 P 和 Q。每个进程将更新两个矩阵上互斥的索引。
我打算做的事情的简单说明如下:
# create "big" matrix
A <- matrix(rnorm(10000), 100, 100)
system.time(
# update each row vector independently using all my cores
r <- mclapply(1:100, mc.cores = 6, function(i) {
# updating ...
A[i,] <- A[i,] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(sum(A[i,]^2))
})
)
使用这种方法有什么缺点吗?是否有更多 R 惯用的替代品?
例如,为了干净(即没有副作用,不可变的计算)返回更新 A[i,] - 0.01
而不是 RMSE
会使编程更复杂并且内存使用达到峰值甚至 运行 内存不足。
使用包 {bigstatsr} 的共享数据按块重新实现您的代码:
N <- 10e3
A <- matrix(rnorm(N * N), N)
library(bigstatsr)
bigA <- as_FBM(A)
library(doParallel)
registerDoParallel(cl <- makeCluster(4))
system.time(
r <- foreach(i = seq_len(N), .combine = 'c') %dopar% {
# updating ...
A[i,] <- A[i,] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(sum(A[i,]^2))
}
) # 11 sec
stopCluster(cl)
registerDoParallel(cl <- makeCluster(4))
system.time(
r2 <- big_apply(bigA, function(X, ind) {
# updating ...
tmp <- bigA[ind, ] <- bigA[ind, ] - 0.01
# return something, i.e. here I'd return the RMSE of this batch instead
sqrt(rowSums(tmp^2))
}, a.combine = 'c')
) # 1 sec
stopCluster(cl)
all.equal(r, r2) # TRUE
同样,更新列而不是行会更好。