Эффективное распараллеливание малых внешних петель и большой внутренней петли в R

#r

Вопрос:

У меня есть следующий R код

 LLL = list()
idx = 1
for(i in 1:3){
  for(j in 1:9){
     for(k in 1:13){
        for(iter in 1:1000000){
       
           if( runif(1,0,1)<0.5 ){
             LLL[[idx]] = rnorm(1,0,1)
             idx = idx   1
          }
       }
     }
  }
}
 

Есть ли способ эффективно распараллелить этот код?

Я думал о том , что у меня есть 351 конфигурации i,j,k , если бы я мог распределить эти конфигурации по ядрам, и каждое ядро выполняло for бы цикл для 1000000 итераций, можно ли было бы реализовать что-то подобное??

Ответ №1:

  1. Вместо того, чтобы звонить rnorm() миллион раз, было бы более эффективно вызвать его один раз с аргументом n = 1000000 .
  2. Чтобы использовать функциональные возможности программирования R, мы должны стараться избегать for() циклов записи. Вместо этого мы можем сначала создать объект, представляющий ваши 351 конфигурацию, а затем выполнить итерацию по этому объекту. Ниже приведен пример того, как это сделать.

Создание конфигураций:

 cfgs <-
  expand_grid(i = 1:3,
              j = 1:9,
              k = 1:13)
 

Код без распараллеливания.

 cfgs |> 
  split(1:nrow(cfgs)) |> 
  lapply((x) rnorm(100000, 0, 1))
 

Для распараллеливания выполнения кода мы можем использовать furrr пакет.

 library(furrr)
plan(multisession)
cfgs |> 
  split(1:nrow(cfgs)) |> 
  future_map((x) rnorm(100000, 0, 1), .options = furrr_options(seed=TRUE))
 

Комментарии:

1. Спасибо за ваш ответ, но я просто использую rnorm его для иллюстрации проблемы. Это может быть любая другая функция, которая не может завершить 1000000 итераций