【发布时间】:2018-02-02 01:34:21
【问题描述】:
我一直在研究处理大型语料库的功能。在其中我使用 doparallel 包。在 50 - 100k 个文档上一切正常。我在 1M 的文档上进行了测试,并收到了上述错误。
但是,当我返回到我之前正在处理的语料库大小时,我仍然遇到同样的错误。我什至尝试过低至 1k 个文档。在控制台调用函数时,一按回车就会产生错误。
虽然我有 15 个核心,但我只测试了两个核心 - 同样的问题。
我还尝试使用rm(list = ls()) 重新启动会话并清除环境
代码:
clean_corpus <- function(corpus, n = 1000) { # n is length of each peice in parallel processing
# split the corpus into pieces for looping to get around memory issues with transformation
nr <- length(corpus)
pieces <- split(corpus, rep(1:ceiling(nr/n), each=n, length.out=nr))
lenp <- length(pieces)
rm(corpus) # save memory
# save pieces to rds files since not enough RAM
tmpfile <- tempfile()
for (i in seq_len(lenp)) {
saveRDS(pieces[[i]],
paste0(tmpfile, i, ".rds"))
}
rm(pieces) # save memory
# doparallel
registerDoParallel(cores = 14)
pieces <- foreach(i = seq_len(lenp)) %dopar% {
# update spelling
piece <- readRDS(paste0(tmpfile, i, ".rds"))
# spelling update based on lut
piece <- tm_map(piece, function(i) stringi_spelling_update(i, spellingdoc))
# regular transformations
piece <- tm_map(piece, removeNumbers)
piece <- tm_map(piece, content_transformer(removePunctuation), preserve_intra_word_dashes = T)
piece <- tm_map(piece, content_transformer(function(x, ...)
qdap::rm_stopwords(x, stopwords = tm::stopwords("english"), separate = F)))
saveRDS(piece, paste0(tmpfile, i, ".rds"))
return(1) # hack to get dopar to forget the piece to save memory since now saved to rds
}
# combine the pieces back into one corpus
corpus <- list()
corpus <- foreach(i = seq_len(lenp)) %do% {
corpus[[i]] <- readRDS(paste0(tmpfile, i, ".rds"))
}
corpus <- do.call(function(...) c(..., recursive = TRUE), corpus)
return(corpus)
} # end clean_corpus function
然后当我运行它时,即使是在一个小语料库上:
> mini_cleancorp <- clean_corpus(mini_corpus, n = 1000) # mini_corpus is a 10k corpus
Show Traceback
Rerun with Debug
Error in mcfork() :
unable to fork, possible reason: Cannot allocate memory
【问题讨论】:
-
我总是会明确地创建集群并在使用后关闭它。您可以尝试使用
stopImplicitCluster。 -
感谢您的提示,在函数中添加它的适当位置是否就在 dopar 块中关闭
}之后? -
是的。但是,您的问题也可能是打开的文件连接过多。我真的不明白为什么要在同一个函数调用中导出到文件并再次导入。是因为记忆的原因吗?不能用
foreach的.combine参数吗? -
是的,内存问题。我一直在努力克服内存限制,这就是我这样做的原因。是的,尝试了 .combine 但达到了内存限制。将每次迭代保存到临时 RDS 文件中,然后删除迭代的存储空间 (return(1)) 似乎确实完成了工作,尽管可能比其他方式慢
-
您在使用少数内核运行时遇到错误,并尝试通过向其添加更多内核来解决此问题?嗯,没有。首先尝试了解错误。无论如何,随着内核数量的增加对内存使用和速度进行基准测试(对于非平凡的任务,您应该始终这样做)。
标签: r parallel-processing tm doparallel