使用 foreach 函数并行计算
Using foreach function to parallelise calculation
我有一个包含 5000 个 csv 文件的文件夹,每个文件属于一个位置并且包含从 1980 年到 2015 年的每日降雨量。文件的示例结构如下:
sample.file <- data.frame(location.id = rep(1001, times = 365 * 36),
year = rep(1980:2015, each = 365),
day = rep(1:365, times = 36),
rainfall = sample(1:100, replace = T, 365 * 36))
我想读取一个文件并计算每年的总降雨量
并再次写入输出。我可以通过多种方式执行此操作:
方法一
for(i in seq_along(names.vec)){
name <- namees.vec[i]
dat <- fread(paste0(name,".csv"))
dat <- dat %>% dplyr::group_by(year) %>% dplyr::summarise(tot.rainfall = sum(rainfall))
fwrite(dat, paste0(name,".summary.csv"), row.names = F)
}
方法二:
my.files <- list.files(pattern = "*.csv")
dat <- lapply(my.files, fread)
dat <- rbindlist(dat)
dat.summary <- dat %>% dplyr::group_by(location.id, year) %>%
dplyr::summarise(tot.rainfall = sum(rainfall))
方法三:
我想使用 foreach
实现此目的。我怎样才能并行上述任务
使用 do parallel
和 for each
函数?
pbapply 包是最简单的并行方法
library (pbapply)
mycl <- makeCluster(4)
mylist <- pblapply(my.files, fread, cl = mycl)
以下是您 foreach request
的骨架。
require(foreach)
require(doSNOW)
cl <- makeCluster(10, # number of cores, don't use all cores your computer have
type="SOCK") # SOCK for Windows, FORK for linux
registerDoSNOW(cl)
clusterExport(cl, c("toto", "truc"), envir=environment()) # R object needed for each core
clusterEvalQ(cl, library(tcltk)) # libraries needed for each core
my.files <- list.files(pattern = "*.csv")
foreach(i=icount(my.files), .combine=rbind, inorder=FALSE) %dopar% {
# read csv file
# estimate total rain
# write output
}
stopCluster(cl)
但是当每次独立迭代的计算时间 (CPU) 高于其余操作时,并行化确实更好。在您的情况下,改进可能很低,因为每个内核都需要具有驱动器访问权限以进行读取和写入,并且由于写入是一项物理操作,因此最好按顺序进行(对硬件更安全,最终效率更高与多个文件的共享位置相比,每个文件在驱动器中有独立的位置,需要索引等来区分它们 OS -- 之前需要确认,这只是一个想法)。
HTH
巴斯蒂安
我有一个包含 5000 个 csv 文件的文件夹,每个文件属于一个位置并且包含从 1980 年到 2015 年的每日降雨量。文件的示例结构如下:
sample.file <- data.frame(location.id = rep(1001, times = 365 * 36),
year = rep(1980:2015, each = 365),
day = rep(1:365, times = 36),
rainfall = sample(1:100, replace = T, 365 * 36))
我想读取一个文件并计算每年的总降雨量 并再次写入输出。我可以通过多种方式执行此操作:
方法一
for(i in seq_along(names.vec)){
name <- namees.vec[i]
dat <- fread(paste0(name,".csv"))
dat <- dat %>% dplyr::group_by(year) %>% dplyr::summarise(tot.rainfall = sum(rainfall))
fwrite(dat, paste0(name,".summary.csv"), row.names = F)
}
方法二:
my.files <- list.files(pattern = "*.csv")
dat <- lapply(my.files, fread)
dat <- rbindlist(dat)
dat.summary <- dat %>% dplyr::group_by(location.id, year) %>%
dplyr::summarise(tot.rainfall = sum(rainfall))
方法三:
我想使用 foreach
实现此目的。我怎样才能并行上述任务
使用 do parallel
和 for each
函数?
pbapply 包是最简单的并行方法
library (pbapply)
mycl <- makeCluster(4)
mylist <- pblapply(my.files, fread, cl = mycl)
以下是您 foreach request
的骨架。
require(foreach)
require(doSNOW)
cl <- makeCluster(10, # number of cores, don't use all cores your computer have
type="SOCK") # SOCK for Windows, FORK for linux
registerDoSNOW(cl)
clusterExport(cl, c("toto", "truc"), envir=environment()) # R object needed for each core
clusterEvalQ(cl, library(tcltk)) # libraries needed for each core
my.files <- list.files(pattern = "*.csv")
foreach(i=icount(my.files), .combine=rbind, inorder=FALSE) %dopar% {
# read csv file
# estimate total rain
# write output
}
stopCluster(cl)
但是当每次独立迭代的计算时间 (CPU) 高于其余操作时,并行化确实更好。在您的情况下,改进可能很低,因为每个内核都需要具有驱动器访问权限以进行读取和写入,并且由于写入是一项物理操作,因此最好按顺序进行(对硬件更安全,最终效率更高与多个文件的共享位置相比,每个文件在驱动器中有独立的位置,需要索引等来区分它们 OS -- 之前需要确认,这只是一个想法)。
HTH
巴斯蒂安