bigstatsr的FBM()在使用并行foreach时无法正确计算矩阵,就像在简单的for循环中运行代码时一样

时间:2019-02-07 07:43:45

标签: r doparallel parallel-foreach snow bigstatsr

我需要估计一个转移矩阵。由于我有大量数据,因此我尝试使用foreach并行运行它,并尝试了FBM()的共享内存函数bigstatsr。而且似乎该功能并非始终都能返回正确的结果。 (有时会。)功能是否可能无法正常工作?

以下是代码正确运行的示例:

x <- c(1,2,1,1,3,4,4,1,2,4,1,4,3,4,4,4,3,1,3,2,3,3,3,4,2,2,3)
n <- length(unique(x))
A <- matrix(nrow = n, ncol = n, 0)
for (t in 1:(length(x) - 1)) {A[x[t], x[t + 1]] <- A[x[t], x[t + 1]] + 1}
A

这是不总是返回正确结果的代码:

library(foreach)
library(doParallel)
library(bigstatsr)

cl <- makeCluster(8)
registerDoParallel(cl)

B <- FBM(n, n)
set.seed(3)

foreach (t = 1:(length(x) - 1))  %dopar% {B[x[t], x[t + 1]] <- B[x[t], x[t + 1]] + 1}
stopCluster(cl)

B[]
identical(A,B[])

使用snow库时也会发生同样的情况

library(snow)
library(bigstatsr)
cl <- makeCluster(8)
f.trans.m <- function(t) {
  D[x[t], x[t + 1]] <<- D[x[t], x[t + 1]] + 1
}
D <- FBM(n, n)
clusterExport(cl, "f.trans.m")
clusterExport(cl, "D")
clusterExport(cl, "x")
parLapply(cl, seq(1,(length(x) - 1)), function(t) f.trans.m(t))
D[]
identical(A,D[])

我是否正确使用了该软件包,或者FBM()中存在错误?

解决方案:

缺少文件包flock提供的文件锁。

B <- FBM(n, n)
lock <- tempfile()
foreach (t = 1:(length(x) - 1))  %dopar% {
  locked <- flock::lock(lock)
  B[x[t], x[t + 1]] <- B[x[t], x[t + 1]] + 1
  flock::unlock(locked)
}

1 个答案:

答案 0 :(得分:0)

对于此特定示例,问题在于值的并行并发更新(参见https://privefl.github.io/blog/a-guide-to-parallelism-in-r/#advanced-parallelism-synchronization)。

在这里,我根本不会使用并行性。我宁愿使用顺序访问器(但矢量化访问器)。

我首先将索引重新组合以递增:

library(dplyr)
ind <- data.frame(i = x[-length(x)], j = x[-1]) %>%
  group_by(i, j) %>%
  count()

然后,我将使用两列矩阵访问器来更新相应的值,而无需使用R循环。

B <- FBM(n, n, init = 0)
ind2 <- as.matrix(ind[1:2])
B[ind2] <- B[ind2] + ind[[3]]