#r #terminal
Вопрос:
У меня есть функция R, которая загружает, обрабатывает и сохраняет много файлов. Вот фиктивная версия:
load_process_saveFiles <- function(onlyFiles = c()){
allFiles <- paste(LETTERS, '.csv', sep = '')
# If desired, only include certain files
if(length(onlyFiles) > 0){
allFiles <- allFiles[allFiles %in% onlyFiles]
}
for(file in allFiles){
# load file
rawFile <- file
# Run a super long function
processedFile <- rawFile
# Save file
# write.csv(processedFile, paste('./Other/Path/', file, sep = ''), row.names = FALSE)
cat('nDone with file ', file, sep = '')
}
}
Он должен выполнить около 30 файлов, и каждый из них занимает около 3 минут. Может потребоваться очень много времени, чтобы выполнить цикл целиком. Что я хотел бы сделать, так это запустить каждый из них отдельно в одно и то же время, чтобы все вместе заняло 3 минуты вместо 3 х 30 = 90 минут.
Я знаю, что могу добиться этого, создав кучу сеансов RStudio или множество вкладок терминала, но я не могу справиться с одновременным открытием такого количества сеансов или вкладок.
В идеале я хотел бы, чтобы все файлы с отдельными функциями были перечислены в одном batchRun.R
файле, который я могу запускать с терминала:
source('./PathToFunction/load_process_saveFiles.R')
load_process_saveFiles(onlyFiles = 'A.csv')
load_process_saveFiles(onlyFiles = 'B.csv')
load_process_saveFiles(onlyFiles = 'C.csv')
load_process_saveFiles(onlyFiles = 'D.csv')
load_process_saveFiles(onlyFiles = 'E.csv')
load_process_saveFiles(onlyFiles = 'F.csv')
Итак, затем запустите $ RScript batchRun.R
из терминала.
Я пытался искать разные примеры на SO, пытаясь выполнить что-то подобное, но у каждого есть некоторые уникальные функции, и я просто не могу заставить его работать. Возможно ли то, что я пытаюсь сделать? Спасибо!
Комментарии:
1. Если вы работаете в Linux, вы можете сделать это в сценарии оболочки вместо R-скрипта с символом амперсанда фоновой задачи
amp;
между вашимиR CMD BATCH . . .
командами (или в цикле).2. Вы также можете получить оболочку Bash в Windows: смотрите Здесь . И в случае, если вы сочтете это полезным, вот раздел руководства по Bash, в котором описывается
amp;
оператор.
Ответ №1:
Пакет parallel
предоставляет вам несколько опций. Одним из вариантов является распараллеливание вызовов load_process_saveFiles
и последовательное выполнение цикла внутри функции. Другой вариант — распараллелить цикл и выполнить вызовы последовательно. Лучший способ оценить, какой подход больше подходит для вашей работы, — это самостоятельно рассчитать их оба.
Вычисление вызовов load_process_saveFiles
параллельно относительно просто с mclapply
помощью параллельной версии базовой функции lapply
(см. ?lapply
):
parallel::mclapply(x, load_process_saveFiles, mc.cores = 2L)
Здесь x
приведен список значений аргумента onlyFiles
и mc.cores = 2L
указывает, что вы хотите разделить вызовы между двумя процессами R.
Оценка цикла внутри load_process_saveFiles
параллельно потребовала бы замены всего for
оператора чем-то вроде
f <- function(file) {
cat("Processing file", file, "...")
x <- read(file)
y <- process(x)
write(y, file = file.path("path", "to", file))
cat(" done!n")
}
parallel::mclapply(allFiles, f, ...)
и переопределение load_process_saveFiles
, чтобы разрешить необязательные аргументы:
load_process_saveFiles <- function(onlyFiles = character(0L), ...) {
## body
}
Тогда вы могли бы сделать, например, load_process_saveFiles(onlyFiles, mc.cores = 2L)
.
Я должен отметить, что mclapply
это не поддерживается в Windows. В Windows вы можете использовать parLapply
вместо этого, но для этого потребуется несколько дополнительных шагов. Они описаны в parallel
виньетке, которую можно открыть из R с vignette("parallel", "parallel")
помощью . Виньетка действует как общее введение в параллелизм в R, поэтому ее все равно стоит прочитать.
Ответ №2:
В этом случае полезен параллельный пакет. И если вы используете ОС Linux, я бы рекомендовал пакет doMC вместо parallel. Этот пакет doMC полезен даже для перебора больших данных, используемых в проектах машинного обучения.