Увеличение m c .core сверх количества логических ядер - PullRequest
3 голосов
/ 09 апреля 2020

Играя с функцией R parallel::mclapply, я обнаружил, что аргумент mc.cores может быть выбран больше, чем количество логических ядер (как указано parallel::detectCores), что приводит к ускорению, превышающему количество логических ядер. Вот минимальный пример (для меня это работало на MacOS и Linux):

sleepy <- function(i) {
    start <- Sys.time()
    Sys.sleep(i)
    as.numeric(Sys.time() - start)
}

mc.cores <- 100L
ntasks   <- 10000L

start <- Sys.time()
out <- parallel::mclapply(2/ntasks*runif(ntasks), sleepy, mc.cores = mc.cores)

real_duration <- as.numeric(Sys.time() - start)
cpu_duration <- sum(unlist(out))

data.frame(logical.cores = parallel::detectCores(),
           mc.cores      = mc.cores,
           speedup       = cpu_duration/real_duration)


##   logical.cores mc.cores  speedup
## 1             8      100 30.49574

Я также попробовал это в более реалистичном примере c, то есть близко к реальному сценарию, который я хочу распараллеливание: это также не привело ни к какой проблеме.

В документации / tutorials для parallel::mclapply я не смог найти ни одного примера, где выбран mc.cores > detectCores(), и, скорее всего, есть очень веская причина для этого.

Может кто-нибудь объяснить, в чем проблемы этой практики? Может ли это быть целесообразно в определенных обстоятельствах, например, когда требования к памяти не являются проблемой?

Ответы [ 2 ]

0 голосов
/ 13 апреля 2020

Я иногда использую mc.cores > detectCores() для регулирования использования памяти. Если вы разделите работу на 10 частей и обработаете их с mclapply и mc.preschedule=F, каждое ядро ​​будет обрабатывать только 10% вашей работы за раз. Например, если для mc.cores установлено значение два, другим 8 «узлам» придется подождать, пока одна часть не закончится, прежде чем начинать новую. Это может быть желательно, если вы сталкиваетесь с проблемами памяти и хотите, чтобы каждый l oop не брал на себя больше, чем он мог бы обработать.

0 голосов
/ 09 апреля 2020

Все, что он делает - это порождает потоки, вы можете думать о них как о легких процессах с общей памятью. Обычно не оптимально порождать больше потоков, чем доступно ядер, из-за издержек переключения контекста. Как правило, в большинстве случаев вам будет лучше, если количество работников будет равно количеству логических ядер вашего процессора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...