Я использовал этот код:
library(parallel)
cl <- makeCluster( detectCores() - 1)
clusterCall(cl, function(){library(imager)})
то у меня есть функция-оболочка, которая выглядит примерно так:
d <- matrix #Loading a batch of data into a matrix
res <- parApply(cl, d, 1, FUN, ...)
# Upload `res` somewhere
Я тестировал на своем ноутбуке с 8 ядрами (4 ядра, гиперпоточность). Когда я запускал его на матрице из 50 000 строк, 800 столбцов, для завершения потребовалось 177,5 с, и большую часть времени 7 ядер были загружены почти на 100% (согласно верхней части), затем он оставался там последние 15 или около того секунд, которые, я думаю, объединяли результаты. Согласно system.time()
, пользовательское время составило 14 секунд, так что это совпадает.
Сейчас я работаю на EC2, 36-ядерном процессоре c4.8xlarge, и я вижу, что он проводит почти все свое время только с одним ядром на 100%. Точнее: есть примерно 10-20 секунд всплеска, когда все ядра используются, затем около 90 секунд только одного ядра на 100% (используется R), затем около 45 секунд других вещей (где я сохраняю результаты и загрузить следующий пакет данных). Я делаю партии из 40 000 строк, 800 столбцов.
Средняя долгосрочная нагрузка, по данным top, колеблется в районе 5,00.
Это кажется разумным? Или есть момент, когда параллелизм R тратит больше времени на коммуникационные накладные расходы, и я должен ограничиться, например, 16 ядер. Какие-нибудь эмпирические правила здесь?
Ссылка: спецификация ЦП Я использую "Linux 4.4 .5-15.26.amzn1.x86_64 (amd64)". R версия 3.2.2 (2015-08-14)
ОБНОВЛЕНИЕ: я пробовал с 16 ядрами. Для наименьших данных время выполнения увеличилось с 13,9 до 18,3 с. Для данных среднего размера:
With 16 cores:
user system elapsed
30.424 0.580 60.034
With 35 cores:
user system elapsed
30.220 0.604 54.395
т.е. служебная часть занимала столько же времени, но параллельный бит имел меньше ядер, поэтому занимал больше времени, и поэтому в целом он занимал больше времени.
Я также пытался использовать mclapply()
, как было предложено в комментариях. Он показался немного быстрее (что-то вроде 330 с против 360 с на конкретных тестовых данных, на которых я пробовал), но это было на моем ноутбуке, где другие процессы или перегрев могли повлиять на результаты. Так что никаких выводов по этому поводу я пока не делаю.
multicore
, напримерmclapply
. Мое ограниченное понимание распараллеливания в R заключается в том, что эта функция позволяет совместно использовать память между ядрами, аparApply
— нет. переключение на эту или другую функцию из пакетаmulticore
может уменьшить коммуникационные издержки. Краткая история: было 2 пакетаmulticore
иsnow
.multicore
работал на *nix-системах (не на windows), аsnow
работал на всех системах. ФункцияparApply
происходит отsnow
. - person lmo   schedule 13.09.2016mclapply
не разделяет память, и, насколько мне известно, общая память принципиально невозможна с форками Unix, за исключением явного отображения общей области (например,mmap
). - person Konrad Rudolph   schedule 14.09.2016mclapply
является копированием при записи для передаваемых переменных. /841830 Это могло бы объяснить ускорение, которое я увидел, сохранив копирование данных в каждый поток, хотя, как я отметил в своем редактировании, мне нужно провести более строгие тесты времени. - person Darren Cook   schedule 14.09.2016fork
. Однако фраза «поделиться полным состоянием R» вводит в заблуждение: как заметил Даррен,fork
на самом деле реализует копирование при записи. Это означает, что состояние фактически полностью изолировано и логически представляет собой независимую копию. Это реализовано с помощью копирования при записи в качестве оптимизации, что означает, что состояние фактически копируется только тогда, когда процесс выполняет операцию записи. Связь между процессами невозможна. Кроме того, копирование при записи происходит очень быстро (= ложные срабатывания). - person Konrad Rudolph   schedule 15.09.2016