您对分支代码与无分支代码的期望适用于汇编和C等低级语言.在低级语言中,无分支代码可以更快,因为它可以防止分支预测失误导致的速度减慢.(注意:这意味着无分支代码can会更快,但不一定会更快.)
Python是一种高级语言.假设您使用的是CPython解释器:对于您执行的每一条字节码指令,解释器都必须在操作码类型上进行分支,通常还有许多其他事情.例如,即使是简单的<
运算符也需要一个分支来判断<
操作码,另一个分支来判断对象的类是否实现了__lt__
方法,更多分支来判断右侧值是否是要执行比较的有效类型,可能还需要几个其他分支.由于这些原因,即使是所谓的"无分支"代码在实践中也会导致大量分支.
由于Python是如此高级,与单个机器代码指令相比,每个字节码指令实际上都做了大量的工作.因此,像这样的简单代码的性能主要取决于需要解释多少字节码指令:
max1
函数必须执行三次局部变量加载:比较、条件跳转和返回.一共六个.
max2
函数执行两次局部变量加载,一次全局变量加载(参考内置max
),还进行函数调用;这需要传递参数,与其他字节码指令相比成本相对较高.除此之外,内置函数本身必须做与您自己的max1
函数相同的工作,所以难怪max2
要慢一些.
max3
函数执行六次局部变量加载、两次比较、两次乘法、一次加法和一次返回.这是12条指令,所以我们预计它需要的时间大约是max1
条指令的两倍.
- 同样地,
max4
会加载五个局部变量,一个存储到局部变量,一个常量,两个减法,一个位移位,一个按位"and",以及一个返回.这又是12条指令.
也就是说,请注意,如果我们直接将max1
与内置函数max
进行比较,而不是将max2
进行额外的函数调用,那么max1
函数仍然比内置函数max
高a bit faster.这可能是因为内置max
接受数量可变的参数,这可能涉及构建一个参数元组,而内置max
函数还有一个分支,用于判断是否使用单个iterable参数(例如max([3, 1, 4, 2])
)调用它,并以不同的方式处理该情况;你的max1
函数不能做这些事情.