• Python性能优化实录


    【向量化计算】将数组逐个相加改为 numpy 数组相加
    @simple_mark_time
    def func1(aa):
        bb = [0] * aa.shape[1]
        for i in range(aa.shape[0]):
            row = aa[i]
            bb = [row[i] + bb[i] for i in range(len(row))]
        return bb
    
    
    @simple_mark_time
    def func2(aa):
        bb = np.full((aa.shape[1],), 0, dtype=np.float64)
        for i in range(aa.shape[0]):
            row = aa[i]
            bb += row
        return bb
    
    
    if __name__ == "__main__":
        a = np.random.random((531, 17280))
        b1 = func1(a)  # func1 use time = 2.3398
        b2 = func2(a)  # func2 use time = 0.008
        print(np.all(np.array(b1) == b2))  # True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    【一次性申请内存】先初始化 Numpy 数组再往 Numpy 数组中填值,而不是先构造 Numpy 数组的列表再转为 Numpy 数组
    @simple_mark_time
    def func1(aa):
        bb = np.full((500, 17280), np.nan, dtype=np.float64)
        for i in range(aa.shape[0]):
            row = aa[i]
            bb[i] = row
        return bb
    
    
    @simple_mark_time
    def func2(aa):
        bb = []
        for i in range(500):
            if i < aa.shape[0]:
                row = aa[i]
            else:
                row = np.full((17280,), np.nan, dtype=np.float64)
            bb.append(row)
        bb = np.array(bb)
        return bb
    
    
    if __name__ == "__main__":
        a1 = np.random.random((50, 17280))
        b1 = func1(a1)  # func1 use time = 0.015
        b2 = func2(a1)  # func2 use time = 0.0489
        print(np.all(b1[~np.isnan(b1)] == b2[~np.isnan(b2)]))  # True
        a2 = np.random.random((500, 17280))
        b1 = func1(a2)  # func1 use time = 0.03
        b2 = func2(a2)  # func2 use time = 0.0369
        print(np.all(b1[~np.isnan(b1)] == b2[~np.isnan(b2)]))  # True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    【逻辑简化】之前的逻辑在第一个模块中构造了 numpy 矩阵,在第二个模块中根据要求调整了 numpy 中行的顺序,重新构造了矩阵。现在在第一个模块构造 numpy 矩阵前,就直接根据要求调整了行的顺序,从而不需要再调整顺序及重新构造矩阵。
    【异步处理】在任务构造进程中,增加线程间共享的缓存队列,令线程 1 将读取任务并写入缓存队列,线程 2 直接将缓存队列的任务写入进程间共享的计算任务队列;从而必须要再等待全部任务读取完成后才将任务添加到计算任务队列。
    【向量化计算】将统计 numpy 矩阵的求和操作从 Python 的原生 sum 函数改为 np.sum 函数
    【向量化计算】使用 numpy 的函数实现数组首尾 0 的数量统计

    验证实例:【Python性能优化实例】计算 numpy 数组首尾为 0 的数量

    【时间复杂度】使用 set 的查找方法,而不是 list 的查找方法

    验证实例:【Python性能优化】元素极少时list和set的查找速度


    • 【逻辑简化】如果需要遍历存在于集合 A 而不存在于集合 B 的,那么遍历差集(A - B)的性能将由于遍历并集(A | B)后,再判断是否只在集合 A 中存在
    • 【空间换时间】根据迭代器初始化集合需要消耗 O(N) 的性能,因此如果集合需要多次使用,则不妨先将集合存储下来
    • 【语法优化】如果需要遍历字典的键及对应的值,那么使用 .items() 将获得更好的性能
    • 【逻辑简化】如果需要判断一个值是否在字典的键中,直接判断即可,不需要将字典的键转为集合再判断
    • 【逻辑简化】如果已经确定键存在于字典中,则没有必要使用 get 方法
    • 【逻辑简化】如果我们频繁地获取某个路径较深的元素,不妨直将将其拿出来,以降低每次从路径中获取消耗的性能
    • 【减少 web 请求】在请求 ES 索引时,如果只需要档案中的部分字段,则需要添加 _source 进行请求
  • 相关阅读:
    [开源]研发管理项目,支持从需求到代码发布全过程全生命周期管理
    SQL教学:掌握MySQL数据操作核心技能--DML语句基本操作之“增删改查“
    浔川画板v5.0——浔川python科技社
    21天学习挑战:经典算法---冒泡排序
    类和对象下
    [论文笔记] Balboa: Bobbing and Weaving around Network Censorship
    pytest unittest temp path单元测试创建临时文件
    -星号菱形-
    提升微服务稳定性与性能:深入剖析Netflix Hystrix框架
    Linux常用命令进阶
  • 原文地址:https://blog.csdn.net/Changxing_J/article/details/128077683