Python性能特征
我正在调整我的一个宠物项目,以提高其性能。我已经破坏了探查器来识别热点,但我认为更好地理解Pythons的性能特征将非常有用 有几件事我想知道: 它的优化器有多聪明? 一些现代编译器拥有非常聪明的优化程序,这些优化程序通常可以获取简单的代码,并使其比任何人类调优代码的尝试运行得更快。根据优化器的智能程度,我的代码最好是“哑巴” 虽然Python是一种“解释”语言,但它似乎可以编译成某种形式的字节码(.pyc)。它这样做有多聪明Python性能特征,python,performance,Python,Performance,我正在调整我的一个宠物项目,以提高其性能。我已经破坏了探查器来识别热点,但我认为更好地理解Pythons的性能特征将非常有用 有几件事我想知道: 它的优化器有多聪明? 一些现代编译器拥有非常聪明的优化程序,这些优化程序通常可以获取简单的代码,并使其比任何人类调优代码的尝试运行得更快。根据优化器的智能程度,我的代码最好是“哑巴” 虽然Python是一种“解释”语言,但它似乎可以编译成某种形式的字节码(.pyc)。它这样做有多聪明 它会折叠常数吗 它是内联小函数还是展开短循环 它会执行复杂的数据/
- 它会折叠常数吗
- 它是内联小函数还是展开短循环
- 它会执行复杂的数据/流分析吗?我没有资格正确解释
- 函数调用
- 类实例化
- 算术
- “更重的”数学运算,如sqrt()
for each x, y position in the image:
create a ray
hit test vs. sphere
hit test vs. triangle
colour the pixel based on the closest object, or black if no hit.
光线跟踪中的算法改进通常是通过在早期消除场景中的对象来实现的。它们可以为复杂场景提供相当大的提升,但如果这种光线跟踪器不能在不费力的情况下针对仅仅两个对象进行测试,那么它将无法处理太多
虽然我意识到基于Python的光线跟踪器无法达到基于C的光线跟踪器的性能,但考虑到实时光线跟踪器(例如,可以在我的计算机上以640x480的速度渲染相当复杂的场景)可以管理15-20 FPS,我希望用Python渲染非常基本的500x500图像在不到一秒钟的时间内就可以完成
目前,我的代码需要38秒。在我看来,这真的不应该花那么长时间
分析显示了在这些形状的实际命中测试例程中花费的大部分时间。这在光线跟踪器中并不特别令人惊讶,这也是我所期望的。这些命中测试的调用计数分别为250000(确切地说是500x500),这表明它们被调用的频率与它们应该被调用的频率完全相同。这是一个相当不错的3%的教科书案例,其中优化是可取的
我计划在改进代码的过程中进行完整的计时/测量工作。然而,如果没有一些关于Python的成本的基本知识,我尝试调优代码只会在黑暗中磕磕绊绊。我想获得一点知识来照亮道路会对我有好处。以下是有趣的地方
- 数据结构
- 算法
如果你想看到真正的速度提升,你需要从根本上重新思考你的数据结构。S.Lott是对的:最大的影响是数据结构和算法。此外,如果您正在进行大量I/O,那么如何管理它将产生很大的不同 但如果您对编译器内部结构感到好奇:它将折叠常量,但不会内联函数或展开循环。内联函数是动态语言中的一个难题 您可以通过反汇编一些已编译代码来查看编译器的功能。在my_file.py中放入一些示例代码,然后使用:
python -m dis my_file.py
这一来源:
def foo():
return "BAR!"
for i in [1,2,3]:
print i, foo()
产生:
1 0 LOAD_CONST 0 (<code object foo at 01A0B380, file "\foo\bar.py", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
4 9 SETUP_LOOP 35 (to 47)
12 LOAD_CONST 1 (1)
15 LOAD_CONST 2 (2)
18 LOAD_CONST 3 (3)
21 BUILD_LIST 3
24 GET_ITER
>> 25 FOR_ITER 18 (to 46)
28 STORE_NAME 1 (i)
5 31 LOAD_NAME 1 (i)
34 PRINT_ITEM
35 LOAD_NAME 0 (foo)
38 CALL_FUNCTION 0
41 PRINT_ITEM
42 PRINT_NEWLINE
43 JUMP_ABSOLUTE 25
>> 46 POP_BLOCK
>> 47 LOAD_CONST 4 (None)
50 RETURN_VALUE
10加载常量0()
3生成函数0
6商店名称0(foo)
4 9设置循环35(至47)
12荷载常数1(1)
15荷载常数2(2)
18荷载常数3(3)
21构建列表3
24天
>>国际热核聚变实验堆18的25(至46)
28店铺名称1(i)
5 31装货单位名称1(i)
34打印项目
35加载\u名称0(foo)
38调用函数0
41打印项目
42打印新行
43绝对值25
>>46波普卢街区
>>47负载常数4(无)
50返回值
请注意,只有模块中的顶级代码被反汇编,如果您还想看到反汇编的函数定义,您需要自己编写更多的代码来递归嵌套的代码对象。如果您已经知道您的算法尽可能快,并且您知道C会快得多,然后,您可能希望将代码的核心在C中实现为一个组件。您可以使用每种语言实际地决定代码的哪一部分用C编写,哪一部分用Python编写
for x in whatever():
anobj.amethod(x)
f = anobj.amethod
for x in whatever():
f(x)
$ python -mtimeit 'for x in (1, 2, 3): pass'
1000000 loops, best of 3: 0.219 usec per loop
$ python -mtimeit 'for x in [1, 2, 3]: pass'
1000000 loops, best of 3: 0.512 usec per loop
$ python -mtimeit -s'Xs=[1,2,3]' 'for x in Xs: pass'
1000000 loops, best of 3: 0.236 usec per loop
$ python -mtimeit -s'Xs=(1,2,3)' 'for x in Xs: pass'
1000000 loops, best of 3: 0.213 usec per loop
* Function calls
* Class instantiation
* Arithmetic
* 'Heavier' math operations such as sqrt()
$ python -mtimeit -s'def f(): pass' 'f()'
10000000 loops, best of 3: 0.192 usec per loop
$ python -mtimeit -s'class o: pass' 'o()'
1000000 loops, best of 3: 0.315 usec per loop
$ python -mtimeit -s'class n(object): pass' 'n()'
10000000 loops, best of 3: 0.18 usec per loop
$ python -mtimeit -s'from math import sqrt' 'sqrt(1.2)'
1000000 loops, best of 3: 0.22 usec per loop
$ python -mtimeit '1.2**0.5'
10000000 loops, best of 3: 0.0363 usec per loop
$ python -mtimeit '1.2*0.5'
10000000 loops, best of 3: 0.0407 usec per loop
$ python -mtimeit '1.2*0.5'
10000000 loops, best of 3: 0.0407 usec per loop
$ python -mtimeit -s'a=1.2; b=0.5' 'a*b'
10000000 loops, best of 3: 0.0965 usec per loop
$ python -mtimeit -s'a=1.2; b=0.5' 'a*0.5'
10000000 loops, best of 3: 0.0957 usec per loop
$ python -mtimeit -s'a=1.2; b=0.5' '1.2*b'
10000000 loops, best of 3: 0.0932 usec per loop
$ python -mtimeit -s'a=1.2; b=0.5' 'a'
10000000 loops, best of 3: 0.039 usec per loop
$ python -mtimeit -s'a=1.2; b=0.5' '1.2'
10000000 loops, best of 3: 0.0225 usec per loop