После долгих размышлений и экспериментов я ответил на свой вопрос. Я не буду ссылаться на оригинальный пример, так как я немного изменил свой подход. Вместо этого я поделюсь некоторыми общими наблюдениями, которые могут помочь людям в подобных ситуациях.
1.) For
циклы более эффективны по памяти, чем lapply
и рекурсивные функции
Когда вы используете lapply, каждый вызов создает копию вашей текущей среды. Вот почему вы можете сделать это:
x <- 5
lapply(1:10, function(i) {
x <- x + 1
x == 6 # TRUE
})
x == 5 # ALSO TRUE
В конце x по-прежнему равен 5, что означает, что каждый вызов lapply
манипулировал отдельной копией x. Это не хорошо, если, скажем, x был на самом деле большим фреймом данных с 10 000 переменных. Циклы for
, с другой стороны, позволяют переопределять переменные в каждом l oop.
x <- 5
for(i in 1:10) {x <- x + 1}
x == 5 # FALSE
2.) Распараллеливать один раз
Распределение Задачи для разных узлов занимают много вычислительных ресурсов и могут свести на нет любые выгоды, которые вы получаете от распараллеливания вашего скрипта. Поэтому вы должны использовать mclapply
по своему усмотрению. В моем случае это означало НЕ помещать mclapply
внутри рекурсивной функции, где ее вызывали от десятков до сотен раз. Вместо этого я разделил начальную точку на 16 частей и выполнил 16 различных операций поиска по дереву на отдельных узлах.
3.) Вы можете использовать mclapply
, чтобы ограничить использование памяти
Если вы разделите работу на 10 частей и обработаете их с помощью mclapply
и mc.preschedule=F
, каждое ядро будет обрабатывать только 10% вашей работы за раз. Например, если для mc.cores
установлено значение два, остальные 8 «узлов» будут ждать завершения одной части, прежде чем начинать новую. Это полезно, если вы сталкиваетесь с проблемами с памятью и хотите, чтобы каждый l oop не брал больше, чем может обработать.
Заключительное примечание
Это одна из наиболее интересных проблем, над которыми я работал до сих пор. Однако рекурсивные древовидные функции являются сложными. Вытяните алгоритм и заставьте себя провести несколько дней вдали от своего кода, чтобы вы могли вернуться с перспективой sh.