parLapply调用fread报错:找不到函数fread的排查求助
问题描述
项目GitHub仓库中的「LASSO code (Version for Antony)」脚本此前正常运行一周,今日突然报错:使用parLapply(或lapply)读取260000个CSV文件时,出现错误提示:
Error in checkForRemoteErrors(val) : 7 nodes produced errors; first error: could not find function "fread"
脚本在小数据集文件夹「last 40」中可正常运行,但在大体积数据集文件夹中失效。已加载data.table库,尝试过匿名函数包裹fread、调整索引写法等多种调用方式均无效,现询问system.time( datasets <- parLapply(CL, paths_list, fun = fread) )是否可行,并寻求解决方法。
相关代码片段
# 加载所有必要包 library(plyr) library(dplyr) library(tidyverse) library(readr) library(stringi) library(purrr) library(stats) library(leaps) library(lars) library(elasticnet) library(data.table) library(parallel) # 创建数据集文件路径列表 folderpath <- "C:/Users/Spencer/Documents/EER Project/12th & 13th 10k" paths_list <- list.files(path = folderpath, full.names = T, recursive = T) # 格式化并排序文件名 DS_names_list <- basename(paths_list) DS_names_list <- tools::file_path_sans_ext(DS_names_list) my_order = DS_names_list |> strsplit(split = "-", fixed = TRUE) |> unlist() |> as.numeric() |> matrix(nrow = length(DS_names_list), byrow = TRUE) |> as.data.frame() |> do.call(order, args = _) DS_names_list = DS_names_list[my_order] paths_list = paths_list[my_order] # 并行读取数据 CL <- makeCluster(detectCores() - 2L) clusterExport(CL, c('paths_list')) library(data.table) system.time( datasets <- parLapply(CL, paths_list, fread) )
已尝试的无效写法
datasets <- parLapply(CL, paths_list, function(i) {fread(i)}) datasets <- parLapply(CL, paths_list, function(i) {fread[i]}) datasets <- parLapply(CL, paths_list, function(i) {fread[[i]]}) datasets <- parLapply(CL, paths_list, \(ds) {fread(ds)}) system.time( datasets <- lapply(paths_list, fread) )
解决方案
1. 核心问题分析
parLapply创建的并行集群节点不会自动继承主节点加载的包,哪怕主节点已经加载data.table,子节点依然无法识别fread函数,这就是报错的根本原因。小数据集可能因单进程执行未触发并行节点加载问题而正常运行,但大数据集触发了并行逻辑,暴露了包未同步的问题。
2. 修正并行读取代码
你询问的system.time( datasets <- parLapply(CL, paths_list, fun = fread) )写法本身没问题,但需要先给所有集群节点加载data.table包,同时可移除不必要的clusterExport操作(parLapply会自动传递迭代的路径参数):
CL <- makeCluster(detectCores() - 2L) # 给所有集群节点加载data.table包 clusterEvalQ(CL, library(data.table)) # 执行并行读取 system.time( datasets <- parLapply(CL, paths_list, fread) ) # 用完集群后关闭,释放资源 stopCluster(CL)
3. 解决lapply失效的问题
如果lapply也报错找不到fread,大概率是出现了命名空间冲突(比如其他包有同名函数),可以明确指定data.table命名空间调用函数:
system.time( datasets <- lapply(paths_list, data.table::fread) )
并行场景下也可以用这种方式避免冲突:
CL <- makeCluster(detectCores() - 2L) system.time( datasets <- parLapply(CL, paths_list, function(path) data.table::fread(path)) ) stopCluster(CL)
4. 大数据集优化建议
处理260000个CSV文件会占用大量内存,建议:
- 使用
fread的select参数指定仅读取需要的列,减少内存占用 - 分批次读取文件,避免一次性加载所有数据到内存
- 考虑使用
data.table的其他高效读取参数(如colClasses指定列类型)提升速度
内容的提问来源于stack exchange,提问作者Marlen

