如何结合并行处理与rowwise函数加速R语言逐行运算效率
并行替换rowwise的实现方案
tidyverse生态下可以直接用furrr包实现兼容dplyr语法的并行运算,完全替代你当前的rowwise逐行计算逻辑,无需大幅修改原有代码:
- 第一步加载并行依赖包:
install.packages(c("future", "furrr"))后引入两个包 - 第二步配置并行环境:使用
plan(multisession, workers = availableCores() - 1)调用可用核心,预留1个核心给系统运行其他程序 - 第三步替换原有
rowwise写法:将逐行调用daily_weather的逻辑换成furrr的并行映射函数即可,注意将函数用到的全局公共对象(如states、预计算的人口栅格)导出到并行子进程避免报错
优先级更高的代码优化方案
你当前代码的最大性能损耗来自重复计算,先做以下优化,性能提升幅度远高于直接并行:
- 人口栅格重采样只做1次:所有PRISM日度气象数据的分辨率完全一致,无需在每次调用
daily_weather时都对人口栅格做一次重采样,提前用任意一个PRISM文件完成人口栅格的重采样后全局复用,直接砍掉70%以上的单步耗时 - 替换raster包为terra包:terra是raster包开发者推出的新一代栅格数据处理包,所有接口兼容,读写、裁剪、重采样速度是raster的3~5倍
- 移除函数内的重复操作:states对象、裁剪范围等公共数据提前全局预处理,不要在函数内重复加载、计算
核心优化后代码示例
library(future) library(furrr) # 其他原有依赖包保持不变 ############ 公共数据预处理 仅运行一次 ############ # 州边界预处理 states <- tigris::states(cb = TRUE, resolution = "20m") %>% filter(!NAME %in% c("Alaska", "Hawaii", "Puerto Rico")) # 人口栅格预处理 pop_rast <- rast("/population/usgrid_data_2000/geotiff/uspop00.tif") pop_crop <- crop(pop_rast, states) # 预重采样人口栅格到PRISM分辨率,全流程复用 sample_prism <- list$files[1] sample_weather <- rast(paste0(sample_prism, "/", sample_prism, ".bil")) pop_rs <- resample(pop_crop, sample_weather) # 优化后的计算函数 daily_weather <- function(varname, filename, date) { weather_rast <- rast(paste0(filename, "/", filename, ".bil")) weather_crop <- crop(weather_rast, states) states[[varname]] <- exact_extract(weather_crop, states, fun = "weighted_mean", weights = pop_rs) res <- as.data.frame(states) %>% arrange(NAME) %>% dplyr::select(NAME, all_of(varname)) return(res) } ############ 并行计算 ############ # 配置并行核心 plan(multisession, workers = availableCores() - 1, seed = TRUE) # 替换原rowwise逐行计算逻辑 days <- list %>% mutate(states = future_pmap( .l = list(files, date1), .f = ~ daily_weather("tmean", .x, .y), .options = furrr_options(globals = c("states", "pop_rs")) )) # 计算完成后关闭并行环境 plan(sequential)
按以上方案优化后,单条数据处理时间可从7秒压缩到1秒以内,搭配8核并行的话,3500条数据总耗时可控制在10分钟以内,后续新增其他气象变量计算也可以直接复用这套逻辑,只需传入对应的变量名参数即可。
内容的提问来源于stack exchange,提问作者bill999
相关产品推荐
相关产品推荐

