Сохранение в цикле foreach (пакет R)?

Я использую пакет foreach для параллельного запуска моделирования Монте-Карло с использованием HPC. У меня нет проблем с тем, что foreach возвращает нужные мне результаты, но мне интересно, можно ли периодически сохранять рабочее пространство. Причина, по которой я спрашиваю, заключается в том, что я должен указать время стены (после чего задание завершается), и поэтому я рискую 1. установить слишком низкое время стены и потерять все до того, как цикл foreach завершится и сохранит мой вывод, или 2. установив консервативное время стены и тратить мою квоту. В идеале я хотел бы иметь возможность периодически сохранять свой вывод, и в этом случае у меня все еще будут данные, если задание завершится.

Например:

results <- foreach (ii = 1:100, .combine = rbind) %dopar% {
 res1 <- ii^2
 res2 <- matrix(sample(1:9,9,replace = F),nrow = 3, ncol = 3)
 if (ii %% 10 == 0){
   save.image("temp_save.RData")
 }
 results <- list(res1,res2)
}
save.image("final_save.RData")

> load("~/final_save.RData")
> results
           [,1]  [,2]     
result.1   1     Integer,9
result.2   4     Integer,9
result.3   9     Integer,9
result.4   16    Integer,9
...

но «temp_save» пуст, предположительно потому, что «результаты» генерируются только после завершения цикла foreach. Есть ли способ получить доступ к этим данным и сохранить их до завершения цикла foreach? Спасибо за вашу помощь.


person yidryi    schedule 10.02.2015    source источник
comment
Вы можете просто сбросить res1 и res2 в файл(ы), этого будет достаточно?   -  person LauriK    schedule 10.02.2015
comment
Какой бэкенд вы используете? делать параллельно?   -  person Steve Weston    schedule 10.02.2015
comment
@Steve Я использую doMC в качестве серверной части.   -  person yidryi    schedule 10.02.2015
comment
@Laurik Если возможно, я бы предпочел сохранить, а не писать, но спасибо за предложение - это определенно вариант, если я не могу использовать сохранение.   -  person yidryi    schedule 10.02.2015
comment
@yidryi Да, но вы также можете сохранить () определенные переменные вместо всего изображения. Может стоит попробовать?   -  person LauriK    schedule 10.02.2015
comment
@LauriK Да, это работает. Прежде чем я ответил, я попытался записать обе переменные в один и тот же файл .txt, но не смог отключить row.names или col.names, что привело к путанице. Запись числа и матрицы в отдельные файлы без имен строк/столбцов работает прекрасно - спасибо! (Мне все равно было бы интересно узнать, есть ли способ использовать сохранение.)   -  person yidryi    schedule 11.02.2015


Ответы (1)


У меня была очень похожая проблема, и я решил ее с помощью метода save(), как указано в комментариях. В частности, мне нравится периодически сохранять свой прогресс при работе с большими наборами данных, чтобы не тратить вычислительные ресурсы впустую, если что-то пойдет не так (например, закончится время на стене). Я лично обнаружил, что save.image() может быть весьма ненадежным при использовании в сложном коде, особенно в среде HPC. Мой код слишком длинный, чтобы воспроизвести его здесь, но это был общий (непроверенный) метод:

# Set up the parallel backend
library(doParallel)
library(foreach)
cl <- parallel::makeCluster(4)
doParallel::registerDoParallel(cl)

# Set up a scratch directory for your intermediate files
intermediate_directory <- 'INTER_DIR'
if (!dir.exists(intermediate_directory) {
    dir.create(intermediate_directory)
}

# Run your parallel loop
foreach(i = 1:100, .export = ls(environment())) %dopar% {

    # Create a unique filename for each interation of the parallel loop
    each_filename <- paste0('RESULT_', as.character(i), '.rda') 
    each_filepath <- file.path(intermediate_directory, each_filename)

    # If the file exists, skip to the next iteration
    if (file.exists(each_filepath)) {
        next
    }

    # Otherwise, run your code
    each_result <- jitter(i, factor = 10)

    # Save the result individually
    save(each_result, file = each_filepath)

    # OR, save the contents of an environment:
    save(list = ls(environment()), file = each_filepath)

}

Результаты могут быть повторно загружены в форму списка после завершения цикла, что в любом случае должно возвращаться foreach. Что-то вроде:

fls <- list.files(intermediate_directory, pattern = '.rda')
result_list <- lapply(fls, function(x) get(eval(load(x)))
person brandonEm    schedule 03.03.2021