Как реализовать параллельные зазубрины в Windows с помощью foreach?

Я хотел бы запускать модели jags параллельно на своем компьютере с Windows с 4 ядрами, но не смог понять, почему моя модель не запускается. Я много искал в Интернете, включая эти сообщения:

http://andrewgelman.com/2011/07/23/parallel-jags-rngs/

http://users.soe.ucsc.edu/~draper/eBay-Google-2013-parallel-rjags-example.txt

Когда я запускаю простой пример (см. код ниже) с %do%, модель работает нормально (конечно, последовательно). Когда я использую %dopar%, я получаю сообщение об ошибке: Error in { : task 1 failed - "Symbol table is empty"

library(rjags)
library(coda)
library(foreach)              
library(doParallel)
library(random)     
load.module("lecuyer")

###  Data generation 
y <- rnorm(100)
n <- length(y)
win.data <- list(y=y, n=n)

# Define model
sink("model.txt")
cat("
    model {
    # Priors
    mu ~ dnorm(0, 0.001)
    tau <- 1 / (sigma * sigma)
    sigma ~ dunif(0, 10)
    # Likelihood
    for (i in 1:n) {
      y[i] ~ dnorm(mu, tau)
    }
}
",fill=TRUE)
sink()

inits <- function(){ list(mu=rnorm(1), sigma=runif(1, 0, 10),
                 .RNG.name = "lecuyer::RngStream", 
                 .RNG.seed = as.numeric(randomNumbers( n = 1, min = 1, max = 1e+06, col = 1 )) ) }
params <- c('mu','sigma')  

cl <- makePSOCKcluster(3)              
clusterSetRNGStream(cl)
registerDoParallel(cl)      
model.wd <- paste(getwd(), '/model.txt', sep='')     # I wondered if the cores were having trouble finding the model.         

m <- foreach(i=1:3, .packages=c('rjags','random','coda'), .multicombine=TRUE) %dopar% {  
                load.module( "lecuyer" )  
                model.jags <- jags.model(model.wd, win.data, inits=inits, n.chains=1, n.adapt=1000, quiet=TRUE)
                result <- coda.samples(model.jags, params, 1000, thin=5)
                return(result)
              }            
stopCluster(cl)
# Error in { : task 1 failed - "Symbol table is empty


sessionInfo()
# R version 3.0.1 (2013-05-16)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# 
# locale:
#   [1] LC_COLLATE=English_Canada.1252  LC_CTYPE=English_Canada.1252    LC_MONETARY=English_Canada.1252
# [4] LC_NUMERIC=C                    LC_TIME=English_Canada.1252    
# 
# attached base packages:
#   [1] parallel  stats     graphics  grDevices utils     datasets  methods   base     
# 
# other attached packages:
#   [1] random_0.2.1     doParallel_1.0.3 iterators_1.0.6  foreach_1.4.1    rjags_3-10       coda_0.16-1     
# [7] lattice_0.20-21 
# 
# loaded via a namespace (and not attached):
#   [1] codetools_0.2-8 compiler_3.0.1  grid_3.0.1      tools_3.0.1  

Подробнее:

Проблема возникает на компьютере с Windows 7 без прав администратора, но не на компьютере с правами администратора. Проблема возникает с Rgui и Rterm, а также с новыми пакетами rjag 3-11. Сообщение об ошибке возникает внутри функции jags.model

Проблема, по-видимому, связана с несоответствием при записи и чтении файлов во временный каталог. Когда я запускаю R, он автоматически создает временную папку. Когда я закрываю R, эта папка автоматически удаляется, если в ней нет файлов.

Например, когда я запускаю R, он создает эту папку: C:\Users\jesse whittington\AppData\Local\Temp\RtmpoBe1gw.

Когда я запускаю модель rjags с

m <- jags.model(file='model.txt', data=win.data, inits=inits, n.chains=3, n.adapt=1000, quiet=FALSE)

Никакие файлы не записываются в этот временный каталог.

Когда я последовательно запускаю 3 цепочки с помощью foreach и %do%, в эту папку записывается 3 временных файла. Эти файлы имеют размер 1 КБ, и когда я открываю их в текстовом редакторе, они кажутся пустыми.

wd <- getwd()                   
cl <- makePSOCKcluster(3, outfile=paste(wd,'/Out_messages.txt', sep=''))   # 3 chains           
clusterSetRNGStream(cl)
registerDoParallel(cl)   
m <- foreach(i=1:3, .packages=c('rjags','random','coda'), .multicombine=TRUE) %do% {  
                load.module( "lecuyer" ) 
                result <- jags.model(file='model.txt', data=win.data, inits=inits, n.chains=1, n.adapt=1000, quiet=FALSE)
                return(result)
              }  
stopCluster(cl) 

Когда я запускаю 3 цепочки параллельно с foreach и %dopar%, в папку ..Temp\RtmpoBe1gw записывается 3 временных файла. Сообщения об ошибках в выходном файле предполагают, что функция ищет РАЗНЫЕ файлы в РАЗНЫХ временных каталогах. Когда я включаю строку для создания каталога и имени временного файла, я вижу, что создаются 3 новых временных папки (позже они удаляются с помощью stopCluster). jags.model ищет в этих трех папках временные файлы и терпит неудачу, потому что в них ничего нет. Таким образом, я подозреваю, что временные файлы записываются в один временный каталог (связанный с родительским сеансом R), а затем происходит сбой при попытке открыть разные временные файлы в трех временных каталогах, созданных в foreach.

wd <- getwd()                   
cl <- makePSOCKcluster(3, outfile=paste(wd,'/Out_messages.txt', sep=''))   # 3 chains           
clusterSetRNGStream(cl)
registerDoParallel(cl)   
m <- foreach(i=1:3, .packages=c('rjags','random','coda'), .multicombine=TRUE) %dopar% {  
                load.module( "lecuyer" ) 
        tmp <- tempfile()
                print(tmp)
                result <- jags.model(file='model.txt', data=win.data, inits=inits, n.chains=1, n.adapt=1000, quiet=FALSE)
                return(result)
              }  
stopCluster(cl) 

Из Out_messages.txt

starting worker pid=4396 on localhost:11109 at 08:34:06.430
starting worker pid=6548 on localhost:11109 at 08:34:06.879
starting worker pid=6212 on localhost:11109 at 08:34:07.418
Loading required package: coda
Loading required package: lattice
Loading required package: coda
Loading required package: lattice
Loading required package: coda
Loading required package: lattice
Linked to JAGS 3.3.0
Loaded modules: basemod,bugs
Linked to JAGS 3.3.0
Loaded modules: basemod,bugs
Linked to JAGS 3.3.0
Loaded modules: basemod,bugs
module lecuyer loaded
module lecuyer loaded
module lecuyer loaded
[1] "C:\\Users\\JESSEW~1\\AppData\\Local\\Temp\\RtmpQbPAVC\\file112c8077a0"  # Note this is from: tmp <- tempfile()
[1] "C:\\Users\\JESSEW~1\\AppData\\Local\\Temp\\RtmpMPMpcY\\file199489564c6"
[1] "C:\\Users\\JESSEW~1\\AppData\\Local\\Temp\\Rtmpk9vMR5\\file18445f6b2fd4"
Compiling model graph
Compiling model graph
Compiling model graph

Warning messages:
1: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Unused variable "y" in data
2: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Unused variable "n" in data
3: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Failed to open file C:\Users\JESSEW~1\AppData\Local\Temp\RtmpQbPAVC\file112c394b4eef
Nothing to compile

4: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Unused initial value for "mu" in chain 1
5: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Unused initial value for "sigma" in chain 1
6: In jags.model(file = "model.txt", data = win.data, inits = inits,  :
  Can't initialize. No nodes in graph (Have you compiled the model?)

Папка RtmpQbPAVC создана, а файл file112c394b4eef не существует.


person Jesse    schedule 24.08.2013    source источник
comment
Я не могу воспроизвести вашу ошибку в Linux: ваш код работает нормально на моей машине. Однако я заметил, что вы не передаете объект кластера cl в registerDoParallel. Я не думаю, что это является причиной вашей ошибки, но это означает, что кластер, который вы фактически будете использовать, не будет кластером, инициализированным clusterSetRNGStream.   -  person Steve Weston    schedule 26.08.2013
comment
Спасибо, что проверил Стива и указал, что я не передал cl для регистрацииDoParallel.   -  person Jesse    schedule 27.08.2013
comment
@Steve Сценарий отлично работает на компьютере с Windows 7 С правами администратора. Он продолжает давать сбой на моем компьютере с Windows 7 без прав администратора. Скрипт завершается с ошибкой при вызове jags.model. Функция обнаруживает ошибки в имени модели и недопустимые функции в инициализации, но не ошибки в win.data.   -  person Jesse    schedule 27.08.2013
comment
Я не могу воспроизвести ошибку в Windows Server 2003 без прав администратора. Можете ли вы подтвердить, что строка jags.model работает правильно при использовании вне строки foreach (последовательно)?   -  person nograpes    schedule 30.08.2013
comment
@nograpes Модель jags.model отлично работает с серийным номером, и она отлично работает, если я изменю %dopar% на %do%. Я установил программу JAGS некоторое время назад в C:/Stats, я думаю (если я правильно помню), потому что она не работала при установке в Program Files (Windows 7). Интересно, запущены ли параллельные процессы в каком-то каталоге, где они не могут создавать файлы. Например, я не могу копировать и вставлять какие-либо файлы в каталог Program Files, потому что у меня нет прав администратора. Спасибо за тестирование!   -  person Jesse    schedule 30.08.2013
comment
Может ли это иметь какое-либо отношение к использованию Rscript по сравнению с R? Может ли исполняемый файл R иметь привилегии, которых нет у Rscript? (Вы можете сказать, что я не знаком с Windows...) Не могли бы вы попробовать запустить версию %do% с помощью Rscript, чтобы увидеть, не приведет ли это к сбою?   -  person Steve Weston    schedule 30.08.2013
comment
Учитывая способ создания кластера, рабочие процессы должны находиться в том же каталоге, что и главный. Вы можете убедиться в этом с помощью clusterEvalQ(cl, getwd()). Вы также можете попробовать запустить простой тест, чтобы увидеть, могут ли рабочие создавать файлы в своем текущем каталоге.   -  person Steve Weston    schedule 30.08.2013
comment
Я удалил пробел из имени каталога, это не повлияло. Точно так же проблема сохраняется при использовании R и RStudio. Вы правы, что clusterEvalQ(cl, getwd()) печатает текущий каталог, как и return(getwd()) в вызове foreach. C:/a_U_drive/R_scripts/Parallel_MCMC.   -  person Jesse    schedule 30.08.2013
comment
Сообщение об ошибке появляется во время этой строки кода в функции 'jags.model': 'model.data ‹- .Call(get_data, p, PACKAGE = rjags)`. Несколько других скомпилированных функций прекрасно работают до этой строки кода.   -  person Jesse    schedule 31.08.2013
comment
Я подозреваю, что перед вызовом get_data что-то пошло не так, но до тех пор об этом не сообщалось. Вы должны убедиться, что видите какие-либо предупреждающие сообщения от воркеров, установив quiet=FALSE при вызове jags.model, а также использовать параметр makePSOCKcluster outfile, чтобы выходные данные не сбрасывались. К сожалению, outfile='' может не работать, если вы используете R GUI, что я обычно и советую.   -  person Steve Weston    schedule 31.08.2013
comment
На CRAN есть новый rjags 3-11, который был выпущен совсем недавно, и похоже, что в нем улучшена проверка ошибок в функции jags.model. Это может привести к более информативному сообщению об ошибке для вашей проблемы, если вам повезет.   -  person Steve Weston    schedule 31.08.2013
comment
Установил ряги 3-11. Та же проблема. Я работал с вариантом outfile, который вы предложили, и немного сузил проблему. Когда я запускаю Rgui или Rterm, R создает временную папку. jags.model записывает файл (по одному на цепочку) в этот временный каталог, а затем снова читает его. При параллельном выполнении jags.model записывает файл в этот каталог, но затем ищет этот файл в ДРУГОМ несуществующем временном каталоге. Основная ошибка: Не удалось открыть файл C:\Users\Jesse... Nothing to compile. Есть еще 5 ошибок, связанных с неиспользуемыми переменными и начальными значениями. Спасибо за вашу помощь!   -  person Jesse    schedule 31.08.2013
comment
Не могли бы вы более подробно изложить эту информацию в вопросе? Либо так, либо поместите это в ответ, если вы выяснили причину проблемы. Я не уверен, что это ошибка в версии R для Windows, в пакете rjags или в чем-то еще.   -  person Steve Weston    schedule 01.09.2013
comment
Это интересно, но почему вы не попробовали пакет jags.parallel или runjags? Это может быть проще, чем пытаться выполнить параллельную работу самостоятельно.   -  person Tomas    schedule 26.01.2014
comment
@Tomas Я столкнулся с похожими проблемами с jags.parallel - я не смог заставить его работать даже с простыми моделями. runjags работали на одних моделях, но вылетали на других. На запуск этих моделей ушло много дней, поэтому я не тратил много времени, пытаясь понять, почему.   -  person Jesse    schedule 27.01.2014
comment
Это депрессивно! Я не хочу программировать все это сам, эти базовые пакеты должны работать! На jags.parallel есть два сообщения, возможно, они помогут вам заставить его работать stackoverflow.com/q/17808575/684229 и < href="http://stackoverflow.com/q/16723036/684229">stackoverflow.com/q/16723036/684229. Но у меня нет окончательного решения. Пожалуйста, дайте мне знать, если вы найдете решение, я должен сделать то же самое.   -  person Tomas    schedule 27.01.2014
comment
@Tomas Сегодня утром я попробовал свои сценарии foreach, и теперь они работают. Понятия не имею, почему — наши сетевые обновления, должно быть, изменили наш доступ для чтения и записи. Сожалеем, что у вас такие же разочарования!   -  person Jesse    schedule 27.01.2014


Ответы (3)


Стив обратил на это мое внимание, но ваш второй пример показывает, что это не проблема с rjags. Я не могу воспроизвести ошибку ни в одном из примеров, используя одну и ту же настройку (Windows 7, R 3.0.1, JAGS 3.0.3, обычный пользователь без прав администратора).

person Martyn Plummer    schedule 02.09.2013
comment
Я согласен. Я предполагаю, что это проблема безопасности/настройки Windows, но мне очень любопытно, почему это происходит только при параллельной работе. Спасибо за внимание к проблеме. - person Steve Weston; 02.09.2013

Поскольку ошибки вызваны записью и чтением файла модели, я предлагаю вам обойти эту проблему, используя функцию textConnection. Это можно использовать для создания объекта подобного файлу без создания реального файла, что позволяет избежать необходимости во временных файлах. Я изменил ваш пример, чтобы продемонстрировать это:

library(rjags)
library(doParallel)
library(random)
load.module("lecuyer")
y <- rnorm(100)
n <- length(y)
win.data <- list(y=y, n=n)
model <- "
  model {
    # Priors
    mu ~ dnorm(0, 0.001)
    tau <- 1 / (sigma * sigma)
    sigma ~ dunif(0, 10)
    # Likelihood
    for (i in 1:n) {
      y[i] ~ dnorm(mu, tau)
    }
  }"
inits <- function() {
  list(mu=rnorm(1), sigma=runif(1, 0, 10),
       .RNG.name="lecuyer::RngStream",
       .RNG.seed=as.numeric(randomNumbers(n=1, min=1, max=1e+06, col=1)))
}
params <- c('mu', 'sigma')
cl <- makePSOCKcluster(3)
clusterSetRNGStream(cl)
registerDoParallel(cl)

m <- foreach(i=1:3, .packages=c('rjags', 'random'),
             .combine='c', .final=mcmc.list) %dopar% {
  load.module( "lecuyer" )
  model.jags <- jags.model(textConnection(model), win.data, inits=inits,
                           n.chains=1, n.adapt=1000, quiet=TRUE)
  coda.samples(model.jags, params, 1000, thin=5)
}

Я также изменил обработку результатов, чтобы значение, возвращаемое циклом foreach, было объектом "mcmc.list", который возвращает функция "coda.samples".

person Steve Weston    schedule 02.09.2013
comment
Я изменил переменные среды TMP, TEMP и TMPDIR на C:\Temp. Все 4 приведенных выше сценария приводят к ошибкам типа «отказано в разрешении». Я также заметил, что в приведенных выше примерах doParallel и parallel временные файлы Rscript создавались в C:\Temp (например, Rscript1a44138d41). - person Jesse; 03.09.2013
comment
@Jesse На данный момент, я думаю, вы должны показать проблему своим системным администраторам. Они могут знать, в чем причина этой проблемы, и могут предложить временный каталог, в котором нет этой проблемы с разрешениями. Или вы можете попробовать другой веб-сайт, специализирующийся на системном администрировании, так как это уже не проблема программирования. - person Steve Weston; 03.09.2013

Я определил источник проблемы. Я могу записывать и читать файлы во временный каталог и из него при обычном использовании R. Параллельно я могу записывать файлы во временные каталоги, но у меня НЕТ прав на чтение файлов.

Проблема возникает как при записи, так и при чтении текстовых файлов (с использованием writeLines и readLines) и файлов csv.

С тех пор я обнаружил, что если я получаю это сообщение: «Ошибка в {: задача 1 не удалась - невозможно открыть соединение», я могу исправить проблему, удалив все временные файлы в TEMP. Для некоторых заблокированных файлов мне нужно выключить и перезагрузить компьютер, прежде чем я смогу удалить необходимые файлы. Тем не менее, в том же сеансе R я могу получить сообщение об ошибке, а затем смогу успешно запустить программу при следующей попытке. Проблема, вероятно, связана с нашим государственным антивирусным программным обеспечением и/или структурой нашего удаленного доступа к сети.

Вот пример, который записывает и читает текстовые файлы для простоты.

library(foreach)              
library(doParallel)
wd <- getwd()
data <- data.frame(x=1:10, y=1:10)

Это прекрасно работает.

modfile <- tempfile()
print(modfile)
# "C:\\Users\\JESSEW~1\\AppData\\Local\\Temp\\RtmpsvYfFk\\filef38a272022"
write.csv(data, modfile, row.names=F)
m <- read.csv(modfile) 

Это не работает

cl <- makePSOCKcluster(3, outfile=paste(wd,'/Out_messages.txt', sep=''))   # 3 chains           
clusterSetRNGStream(cl)
registerDoParallel(cl)   
m <- foreach(i=1:3) %dopar% {  
  modfile <- tempfile()
  write.csv(data, modfile, row.names=F)
  x <- read.csv(modfile)
  return(x)
}  
# Error in { : task 1 failed - "cannot open the connection"
stopCluster(cl) 

Вот вывод из Out_message.txt. Обратите внимание на «Отказано в доступе» справа.

starting worker pid=6852 on localhost:11611 at 22:09:19.488
starting worker pid=6984 on localhost:11611 at 22:09:19.926
starting worker pid=3384 on localhost:11611 at 22:09:20.441
Warning message:
  Warning message:
  In file(con, "r") :
  cannot open file 'C:\Users\JESSEW~1\AppData\Local\Temp\Rtmp6dEZLP\file1ac44a506032': Permission denied
In file(con, "r") :
  cannot open file 'C:\Users\JESSEW~1\AppData\Local\Temp\RtmpuydRvR\file1b48185f2a2d': Permission denied
Warning message:
  In file(con, "r") :
  cannot open file 'C:\Users\JESSEW~1\AppData\Local\Temp\RtmpAbOIng\filed382ef37d51': Permission denied
person Jesse    schedule 02.09.2013
comment
Это большой прогресс, но остается вопрос, почему использование parallel/doParallel/foreach создает эту странную ситуацию. Мне все еще интересно, имеет ли это какое-то отношение к Rscript. Если вы изолируете тело цикла foreach в сценарий, произойдет ли сбой с Rscript и успех с 'R -f'? Было бы здорово, если бы это было так просто. - person Steve Weston; 02.09.2013
comment
Может оказаться полезным просмотреть список разрешений для временных каталогов с помощью команды Windows icacls. Получите имена временных каталогов с помощью tdirs <- clusterEvalQ(cl, tempdir()), а затем выполните icacls из R, используя, например, system(paste("icacls", tdirs[1]), input=""). Это может пролить свет на то, почему мастер может читать и записывать файлы в свой временный каталог, в то время как рабочие кластера могут записывать файлы только в свои собственные временные каталоги. - person Steve Weston; 02.09.2013
comment
Проблема возникает, когда я использую Rgui.exe и R.exe. Разрешения на печать одинаковы для Rgui.exe и R.exe, а также для главного временного каталога и кластерного временного каталога. Печатные разрешения: C:\Users\JESSEW~1\AppData\Local\Temp\RtmpqeRGYq NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Administrators:(I)(OI)(CI)(F) APCA2\Jesse Whittington:(I)(OI)(CI)(F) - person Jesse; 02.09.2013
comment
Обратите внимание, что рядом с папкой C:\Users\jesse whittington\ стоит значок замка. Я (к сожалению) использую правительственный ноутбук, который, вероятно, имеет дополнительные ограничения на разрешения. Проблема возникает, когда я вхожу в сеть и когда я не в сети. Я могу вручную копировать, вставлять и открывать временные файлы в папке tempdir кластера. - person Jesse; 02.09.2013
comment
Вы можете выполнить: Rscript -e 'x=tempfile();writeLines(letters,x);readLines(x)' - person Steve Weston; 02.09.2013
comment
В Windows, я думаю, вам нужно использовать двойные кавычки вокруг выражения, следующего за -e, поэтому вместо этого выполните это: Rscript -e "x=tempfile();writeLines(letters,x);readLines(x)". - person Steve Weston; 02.09.2013
comment
Хорошо, я понимаю, что вы имеете в виду под Rscript. Это работает C:\Stats\R\R-3.0.1\bin\Rscript.exe -e 'x=tempfile();writeLines(letters,x);readLines(x)'. Использование Rscript и foreach не работает с %do% или %dopar%. Rscript -e 'library(foreach);library(doParallel);cl <- makePSOCKcluster(3);registerDoParallel(cl);m <- foreach(i=1:3) %dopar% {x=tempfile();writeLines(letters,x);readLines(x)};stopCluster(cl)'. В сообщениях говорится: Система не может найти указанный файл. Одна вещь, которая может повлиять на мои проблемы, заключается в том, что наш ИТ-отдел устанавливает наш сетевой диск (U:/) в качестве диска по умолчанию. - person Jesse; 02.09.2013
comment
Теперь я вижу сообщение с двойными кавычками. Rscript -e "x=tempfile();writeLines(letters,x);readLines(x)" говорит, что разрешение отклонено. - person Jesse; 03.09.2013
comment
давайте продолжим это обсуждение в чате - person Steve Weston; 03.09.2013