使用future_mapply并行调用r5r的detailed_itineraries报错及提速疑问
问题:r5r结合future.apply并行计算报错及提速验证
我正在测试默认支持并行计算的r5r包,因需快速处理大量起讫点(OD)数据,尝试使用R的future.apply工具调用detailed_itineraries函数以进一步提速。编写代码如下:
library(r5r) library(sf) library(tigris) library(future.apply) library(rJava) library(tidyverse) r5r_core <- setup_r5(data_path = path, verbose = FALSE) tracts2 <- tracts(state = "PA", county = "Philadelphia", year=2019)%>% select(GEOID)%>% st_centroid()%>% st_transform("EPSG:4326")%>% arrange(GEOID)%>% rename(id = GEOID)%>% mutate(lon = unlist(map(geometry,1)), lat = unlist(map(geometry,2)))%>% st_set_geometry(NULL)%>% as.data.frame() mode <- c("WALK", "TRANSIT") max_walk_time <- 30 # minutes departure_datetime <- as.POSIXct("14-06-2023 8:30:00", format = "%d-%m-%Y %H:%M:%S") plan(multicore) fn <- function(x, y){ detailed_itineraries(r5r_core = r5r_core, origins = x, destinations = y, mode = mode, departure_datetime = departure_datetime, max_walk_time = max_walk_time, walk_speed = 4.5, max_trip_duration = 60, shortest_path = TRUE, all_to_all = FALSE, drop_geometry = TRUE, progress= TRUE) } future_mapply(fn, tracts2, tracts2)
运行后出现错误:
Error in assign_points_input(origins, "origins") : 'origins' must be either a 'data.frame' or a 'POINT sf'.
想请教该错误的原因,同时确认这种并行方式是否真能提升分析速度。
错误原因分析
future_mapply的参数传递逻辑导致了这个错误:
- 当传入
data.frame类型的tracts2作为参数时,future_mapply会按列拆分输入,而非按行。也就是说fn函数里的x和y拿到的是tracts2的单个列(比如id列、lon列),而不是包含id、lon、lat的完整行数据框。 detailed_itineraries要求origins和destinations必须是包含id、lon、lat字段的data.frame或POINT sf,单个列不符合要求,因此触发类型检查错误。
修复方案
调整并行逻辑,确保每个子进程拿到完整的单行数据框作为起讫点:
- 先将
tracts2按行拆分成列表,每个元素是一行数据框:
tracts_list <- split(tracts2, seq(nrow(tracts2)))
- 使用
future_map2替代future_mapply,传递拆分后的列表:
plan(multicore) # Windows系统需改用plan(multisession) fn <- function(origin_row, dest_row){ detailed_itineraries(r5r_core = r5r_core, origins = origin_row, destinations = dest_row, mode = mode, departure_datetime = departure_datetime, max_walk_time = max_walk_time, walk_speed = 4.5, max_trip_duration = 60, shortest_path = TRUE, all_to_all = FALSE, drop_geometry = TRUE, progress= FALSE) # 关闭子进程进度条,避免输出混乱 } results <- future_map2(tracts_list, tracts_list, fn)
- 额外注意:
r5r_core是基于rJava的对象,在multicore(fork模式)下可能存在跨进程复制问题,建议Linux/macOS用户保持multicore,Windows用户必须使用multisession,或者在每个子函数内重新初始化r5r_core以避免对象传递问题。
并行方式的提速效果说明
这种并行方式确实能提升大OD量的处理速度,结合r5r本身的并行机制说明如下:
- r5r的
setup_r5默认会设置n_threads为系统核心数,内部计算(如路径搜索)已使用多线程,但这种内部并行是针对单个请求的,当处理大量独立OD对时,单进程的r5r无法充分利用所有CPU核心。 - 通过future.apply将OD对拆分成多个独立任务,分配到不同进程并行处理,相当于同时运行多个r5r实例,能充分利用空闲CPU核心,在OD数量足够多、CPU核心充足的场景下,能显著缩短总处理时间。
- 注意:如果OD对数量远小于CPU核心数,并行的提速效果会不明显,甚至因为进程切换开销导致变慢。
内容的提问来源于stack exchange,提问作者transitmapper
相关产品推荐
相关产品推荐

