如何在Python中高效并行执行函数生成列表?优化现有耗时代码
优化并行执行效率的方案
你的代码耗时过长的核心问题是重复调用了slicecatch(i)——每个i在budx和budy中都被处理了一次,相当于做了两倍的IO/数据加载工作,同时两次启动Parallel也会带来额外的进程启动开销。以下是针对性的优化方案:
核心优化思路
- 合并两个计算逻辑到单个函数中,每个
i只调用一次slicecatch(i),同时计算两个所需的比值 - 只启动一次并行任务,避免多次初始化并行池的开销
- 统一异常处理逻辑,减少冗余代码
优化后的代码
import time import random from joblib import Parallel, delayed catchments = 50 #define number of catchments to plot here randomlist = random.sample(range(2, 2100), catchments) def compute_bud_values(i): try: catch = slicecatch(i) prec_mean = catch.Prec.mean().values # 一次获取catch后,同时计算两个比值 budx_val = catch.PETNatVeg.mean().values / prec_mean budy_val = catch.TotalET.mean().values / prec_mean return (budx_val, budy_val) except IndexError as e: # 异常时返回两个None,保证结果列表长度一致 return (None, None) start_time = time.perf_counter() # 一次并行执行所有任务,得到包含二元组的结果列表 results = Parallel(n_jobs=-1)(delayed(compute_bud_values)(i) for i in randomlist) # 将结果拆分到两个列表中 bud_x, bud_y = zip(*results) # 如果需要列表类型(zip返回元组),可以转换: # bud_x = list(bud_x) # bud_y = list(bud_y) finish_time = time.perf_counter()
额外优化建议
- 如果
slicecatch(i)是IO密集型操作(比如读取文件),可以加入缓存机制,用functools.lru_cache缓存slicecatch的结果(注意i要是可哈希类型),进一步避免重复计算:from functools import lru_cache @lru_cache(maxsize=None) def slicecatch(i): # 原slicecatch的实现代码 ... - 若计算是CPU密集型,
joblib默认的多进程模式没问题;如果是IO密集型,可尝试改用多线程模式(backend="threading"),减少进程切换开销:results = Parallel(n_jobs=-1, backend="threading")(delayed(compute_bud_values)(i) for i in randomlist)
内容的提问来源于stack exchange,提问作者Zeeshan Asghar
相关产品推荐
相关产品推荐

