Оптимизация вложенных допаров foreach в R

Я хотел бы получить информацию о том, как устроен мой код ниже. Хотелось бы знать, нужно ли его организовать по-другому, чтобы выполнять быстрее. В частности, нужно ли мне по-разному использовать foreach и dopar во вложенных циклах. В настоящее время основная часть работы приходится на внутренний цикл (ddply с 1-8 переменными разбивки, каждая из которых имеет 10-200 уровней), и это то, что я выполняю параллельно. Я опустил детали кода для простоты.

Любые идеи? Мой код, организованный ниже, действительно работает, но занимает несколько часов на 6-ядерном компьютере с 41 ГБ памяти. Набор данных не такой большой (‹ 20 тыс. записей).

for(m in 1:length(Predictors)){  # has up to three elements in the vector

  # construct the dataframe based on the specified predictor
  # subset the original dataframe based on the breakdown variables, outcome, predictor and covariates

  for(l in 1:nrow(pairwisematrixReduced)){  # this has 1-6 rows;subset based on correct comparison groups

    # some code here

    cl <- makeCluster(detectCores())  
    registerDoParallel(cl) 

    for (i in 1:nrow(subsetting_table)){  # this table has about 50 rows

      # this uses the columns specified by k in the glm; the prior columns will be used as breakdown variables
      # up to 10 covariates
      result[[length(result) + 1]] <- foreach(k = 11:17, .packages=c('plyr','reshape2', 'fastmatch')) %dopar% {   

        ddply( 
          df,
          b,   # vector of breakdown variables
          function(x) { 

           # run a GLM and manipulate the output

          ,.parallel = TRUE) # close ddply
      } # close k loop -- set of covariates
    } # close i loop -- subsetting table
  } #close l -- group combinations
} # close m loop - this is the pairwise predictor matrix 

stopCluster(cl)
result <- unlist(result, recursive = FALSE)
tmp2<-do.call(rbind.fill, result)

person Josh    schedule 26.12.2016    source источник
comment
Я рекомендую выполнить следующие команды и прочитать о разнице между %dopar% и %:%. vignette("foreach") и vignette("nested")   -  person manotheshark    schedule 26.12.2016
comment
foreach находится внутри i   -  person Josh    schedule 26.12.2016
comment
Я пропустил это foreach, но я бы порекомендовал прочитать виньетку, о которой я упоминал выше. Будет проще написать операторы foreach и ddply как операторы foreach, в одном из которых будет использоваться %dopar, а в другом - %:%. Виньетка рассказывает о преимуществах параллелизма внутреннего и внешнего цикла. Вам нужно будет протестировать свой собственный код, поскольку он зависит от данных, но это делается так же просто, как поменять местами %dopar% и %:% между двумя foreach.   -  person manotheshark    schedule 26.12.2016
comment
Вы также, вероятно, увидите увеличение скорости, перемещая makeCluster и registerDoParallel за пределы циклов for, поскольку вы создаете m * l раз, когда одного раза должно быть достаточно.   -  person manotheshark    schedule 27.12.2016


Ответы (1)


Скопировано из vignette("nested")

3 Использование %:% с %dopar%

При распараллеливании вложенных циклов всегда возникает вопрос, какой цикл распараллеливать. Стандартный совет...

Вы также используете foreach %dopar% вместе с ddply и .parallel=TRUE. С шестиядерным процессором (и, предположительно, гиперпоточностью) блок foreach запустит 12 сред, а затем ddply запустит 12 сред в каждой из них для 144 одновременных сред. foreach следует изменить на %do%, чтобы соответствовать тексту вашего вопроса о параллельном запуске внутреннего цикла. Или, чтобы сделать его чище, измените оба на foreach и используйте %dopar% для одного цикла и %:% для другого.

person manotheshark    schedule 26.12.2016