Распараллеливание с несколькими ядрами на одного рабочего

В некоторых пакетах R есть функции, которые могут выполнять свою работу параллельно, если доступно несколько ядер — например, пакет rstan может запускать несколько цепочек MCMC параллельно. Когда я запускаю несколько процессов Стэна параллельно друг другу, используя, например, doSNOW и foreach, я хочу, чтобы мой код работал параллельно на обоих уровнях*. Вместо этого процессы Стэна отдаются на откуп моим рабочим процессам и, кажется, последовательно запускают свои цепочки там, как будто, будучи назначенными на ядро, они не могут видеть другие ядра машины и думают, что они находятся на одном-единственном ядре. основная машина.

Есть ли способ создать кластеры из 4-ядерных узлов, которые я могу передать какому-нибудь пакету распараллеливания в R, чтобы получить максимальную эффективность от моей машины?

*скажем, у меня есть машина с 36 ядрами, и 9 сценариев Stan выполняются с 4 цепями в каждом. В идеале у меня есть 36 процессов, которые я мог бы запустить одновременно. Прямо сейчас я использую 9 ядер одновременно, и это занимает в 4 раза больше времени, чем я надеюсь.


person Empiromancer    schedule 22.03.2018    source источник
comment
Можете ли вы привести воспроизводимый пример?   -  person F. Privé    schedule 22.03.2018
comment
Удалось ли вам получить рабочую версию этого? Я пытаюсь сделать то же самое с rstan.   -  person Geoffrey    schedule 29.03.2020


Ответы (1)


Предполагая, что у вас есть веская причина не создавать 36 параллельных рабочих процессов напрямую (например, если у вас есть вычислительный кластер или что-то в этом роде), тогда должно работать следующее (на примере doParallel):

library(doParallel)

# create "outer" workers
outer_workers <- makeCluster(2L)
# register outer_workers
registerDoParallel(outer_workers)

# create "inner" workers
clusterEvalQ(outer_workers, {
    library(doParallel)
    inner_workers <- makeCluster(2L)
    # register inner_workers
    registerDoParallel(inner_workers)

    NULL
})

# assuming you use foreach directly
foreach(i = 1L:2L) %dopar% {
    foreach(j = 1L:2L) %dopar% {
        # code
    }

    NULL
}

# stop inner workers
clusterEvalQ(outer_workers, {
    stopCluster(inner_workers)
    registerDoSEQ()
    NULL
})

stopCluster(outer_workers); registerDoSEQ()

В этом примере всего создается 4 процесса: 2 внешних и 2 внутренних. В вашем примере у вас может быть 9 внешних и 4 внутренних процесса.

person Alexis    schedule 05.06.2018