Увеличение mc.cores сверх количества логических ядер

Поэкспериментировав с функцией 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

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

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

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


person Niklas Hartung    schedule 09.04.2020    source источник
comment
Что такое parallel::detectCores(logical = FALSE)?   -  person F. Privé    schedule 09.04.2020


Ответы (2)


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

person Daniel Freeman    schedule 13.04.2020

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

person wklm    schedule 09.04.2020
comment
Это неправда. Обычно рекомендуют оставить хотя бы одно ядро ​​для ОС или использовать только физические ядра. - person F. Privé; 09.04.2020