FBM () bigstatsr не правильно вычисляет матрицу при использовании параллельного foreach, как это происходит, когда код выполняется в простом цикле for - PullRequest
0 голосов
/ 07 февраля 2019

Мне нужно оценить Матрицу перехода.Поскольку у меня много данных, я попытался запустить их параллельно, используя 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

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 голосов
/ 07 февраля 2019

В этом конкретном примере проблема заключается в параллельном параллельном обновлении значений (см. https://privefl.github.io/blog/a-guide-to-parallelism-in-r/#advanced-parallelism-synchronization).

. Здесь я бы вообще не использовал параллелизм. Я бы предпочел перейти на последовательное (но векторизованное)accessor.

Сначала я бы перегруппировал индексы для приращения:

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]]
...