Обновите одну общую переменную в параллельном цикле `foreach` - PullRequest
0 голосов
/ 10 февраля 2019

Мне нужно выполнить анализ перестановки для данных нейровизуализации, который обычно будет очень требовательным к памяти, если мы будем хранить каждое решение перестановки в памяти.Чтобы избежать этой проблемы, мы отслеживаем, во сколько раз результаты перестановок превышают значения эталона, поэтому все, что нам нужно, - это один вектор превышения количества.Это прекрасно работает в цикле for, но я не могу понять, как распараллелить задачу, используя foreach.Моя проблема в том, что я не могу найти способ обновить одну общую переменную (или объект) отдельными foreach работниками.Все онлайн-рекомендации - создать таблицу данных со всеми выходными данными цикла foreach, но это неэффективно для анализа больших данных.Я мог бы попытаться сделать так, чтобы все foreach работники записывали в общий файл, но тогда было бы другой проблемой, как обработать такой файл для получения подсчета по столбцам (не элегантное решение).Тем не менее, концептуально решение должно быть простым: каждый foreach работник должен прочитать и изменить, ссылаясь на один общий вектор, сохраняемый в памяти.

Я использую для анализа пакет ANTsR, в котором изображения хранятся как объекты S4 (указатели на память), чтобы избежать дублирования информации при передаче аргументов функциям и т. Д. Поскольку объекты S4 являются указателями на память, яможет заставить foreach обновить отдельный объект S4, но похоже, что указатели на S4 неправильно передаются при передаче foreach работникам.

У кого-нибудь есть решение?

library(ANTsR)

# load example image and make a mask

img = antsImageRead(getANTsRData( "r16" ))
mask = getMask(img)


###########################################

library(doParallel) 
ncores = 2
registerDoParallel(cores=ncores) 

###############################

# parallel loop cannot update img S4 object

foreach (i=1:10, .combine='c', .export = c('img','mask'), 
         .packages = c('ITKR', 'ANTsRCore', 'ANTsR') ) %dopar% {

  # max(img) # output: 254
  # print(img@pointer) # output: <pointer: (nil)>
   img[mask] = 0 # output: no change to img
}

# standard for loop works

for (i in 1:10)  {
  # print(img@pointer) output: <pointer: 0x5510610>
  # max(img) # output: 254
   img[mask] = 0 # output: img black
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...