在导入方式及 代码运行访问 命名空间中的变量时,先在本地变量寻找 再到全局变量寻找的优化
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import math
import timeit
from math import sin
def tight_loop_very_slow(iterations):
"""
每次循环 要先找全局变量中的math模块,再去 模块中找 sin方法,极慢
"""
result = 0
for i in range(iterations):
result += math.sin(i)
def tight_loop_slow(iterations):
"""
每次循环 要去 全局变量中找 sin方法,较慢
"""
result = 0
for i in range(iterations):
result += sin(i)
def tight_loop_fast(iterations):
"""
每次循环在本地变量中找到 sin方法,较快
"""
result = 0
local_sin = sin
for i in range(iterations):
result += local_sin(i)
if __name__ == '__main__':
x = timeit.repeat(stmt="tight_loop_very_slow(10000000)", number=2, globals=globals())
print(x)
x = timeit.repeat(stmt="tight_loop_slow(10000000)", number=2, globals=globals())
print(x)
x = timeit.repeat(stmt="tight_loop_fast(10000000)", number=2, globals=globals())
print(x)
代码运行时间分析 结果如下:
总结:
- 推荐使用 如上示例的 tight_loop_fast() 函数;
- 在导入模块时,最好 使用 from xxx import xxx 导入具体的方法,而不是 粗略的导入一个模块;
- 在for循环内部(特别是 for循环次数达到10万级别时)需要 调用其他模块方法时, 可以将 其他模块方法 在本函数中先 赋值一次;这样 在本地变量中就能找到对应方法;
尽量使用 迭代器 代替list
# -*- coding: utf-8 -*-
"""
(C) rgc
All rights reserved
create time '2021/1/21 18:25'
Usage:
"""
from memory_profiler import profile
@profile
def use_list():
"""
使用list,内存需要存储所有符合条件的数据,再进行 长度判断
:return:
"""
print(len([1 for n in range(1000000) if n % 3 == 0]))
@profile
def use_generator():
"""
使用生成器,每次只 生成一个数据给 sum使用,这样内存执行存储一个数据即可
:return:
"""
print(sum((1 for n in range(1000000) if n % 3 == 0)))
if __name__ == '__main__':
use_list()
use_generator()
内存分析 运行结果如下:
总结:
- 在循环数量较大时(万级别以上), 且满足需求前提下,尽量使用 生成器 代替list, 用来减少内存消耗;
- 在时间消耗上, 两者差不多;
- python的 itertools(迭代器模块) 里有很多 能用到的 迭代器方法,目的为了高效且节约内存;
尽量进行矢量计算
就是cpu尽量使用L1/L2 的缓存中的数据计算,而不用再从 内存中取数据; cpu从内存中取数据 是非常浪费时间的行为; 使用numpy的矢量计算可以尽量避免此行为
尽量使用 就地操作 如 a+=1 而不要用a=a+1; 也就是 内存ID尽量不要换;
如下内容引用自 <<python高性能编程>>
Numba 可能提供了快速的性能提升,而几乎不需要什么工作量,但是它也会有在
你的代码上可能不会工作得很好的限制。这也是一个相对年轻的项目。
Cython 可能为最广泛的问题集提供了最好的结果,但是它的确需要更多的工作量
和交额外的“支持税”,这要归因于它混合使用了 Python 和 C 注解。
如果你不使用 numpy 或其他难以移植的 C 扩展,PyPy 是一个强力的选择。
如果你想要编译成 C 并且不使用 numpy 或其他外部库,Shed Skin 可能是有用的。
如果你正在部署一个生产工具,那么你可能想要坚持使用理解良好的工具—
Cython 应该是你的主要选择,你可能想要查阅在 12.2 节。PyPy 也被用于产品设
置(看看 12.5 节)。
如果你工作于少量的数值处理需求,注意 Cython 的缓存接口接受 arrary.array
矩阵——这是一个把一块数据传给 Cython 的简单方法,可用来做快速的数值处理
而不用添加 numpy 作为项目依赖。
整体而言,Pythran 和 Numba 是年轻但是很有前景的项目,而 Cython 十分成熟。
PyPy 到现在被视为相对成熟,并且应该一定要有长期的过程来评估。
参考书籍:
<<python高性能编程>>