如何优化对多组列表的列表批量应用函数的代码执行速度?
如何优化对多组列表的列表批量应用函数的代码执行速度?
看起来你的核心瓶颈在于pertes_etats函数里的列表推导式+逐个创建numpy数组——这在数据量大的时候会产生大量的Python循环开销和数组创建成本。咱们可以利用numpy的向量化特性来大幅提升效率,下面是具体的优化思路和实现:
1. 优化单个pertes_etats函数
原函数里的列表推导式是Python层面的循环,而且每次迭代都要创建一个新的numpy数组,这是低效的关键。我们可以一次性把所有系数和数据转换成numpy数组,再用高度优化的numpy内置操作完成计算:
import numpy as np def pertes_etats_opt(P, n): if not P: return np.ones(n) # 一次性提取所有系数和数据,转换为numpy数组 coeffs = np.array([x[0] for x in P]) data = np.array([x[1] for x in P]) # 用np.dot直接完成加权求和,这是BLAS优化的操作,速度极快 return np.dot(coeffs, data)
为什么这更快?
- 避免了Python层面的循环:numpy的操作是在C语言层面执行的,远快于Python循环。
- 减少数组创建开销:一次性转换为二维数组,代替多次创建小数组的成本。
np.dot是经过BLAS库优化的矩阵乘法操作,比手动广播求和的效率更高。
用你给出的例子测试:
PR = [[1,[1,2,3]],[3,[4,5,6]]] print(pertes_etats_opt(PR, 3)) # 输出:[13 17 21],和原函数结果一致
2. 进一步优化:提前预处理数据
如果PF、PJ、PR这些数据需要被多次调用处理,我们可以提前把它们转换成numpy格式的系数+数据对,避免每次调用函数时重复解析列表:
# 预处理函数:把列表的列表转换为(coeffs数组, data数组)的元组 def preprocess_data(P): if not P: return None coeffs = np.array([x[0] for x in P]) data = np.array([x[1] for x in P]) return (coeffs, data) # 提前预处理三组数据 PF_processed = preprocess_data(PF) PJ_processed = preprocess_data(PJ) PR_processed = preprocess_data(PR) # 适配预处理数据的计算函数 def pertes_etats_preprocessed(processed_data, n): if processed_data is None: return np.ones(n) coeffs, data = processed_data return np.dot(coeffs, data) # 批量调用 PF, PJ, PR = [pertes_etats_preprocessed(p, n) for p in (PF_processed, PJ_processed, PR_processed)]
这种方式在多次重复计算时能节省大量的列表解析和数组转换时间,进一步提升整体效率。
3. 额外小建议
- 确保你的numpy是使用BLAS/LAPACK优化版本(比如OpenBLAS、MKL),这能让
np.dot等操作的性能最大化。 - 如果
n的大小固定,在预处理时可以指定数组的dtype(比如dtype=np.int32或np.float64),避免numpy自动推断类型带来的开销。
备注:内容来源于stack exchange,提问作者Fitz
相关产品推荐
相关产品推荐

