我在python中找到了两个无分支函数,它们可以找到两个数字的最大值,并将它们与if语句和内置的max函数进行了比较.我认为无分支函数或内置函数将是最快的,但最快的是if语句函数.有人知道这是为什么吗?以下是功能:

If语句(25000次操作2.16秒):

def max1(a, b):
    if a > b:
        return a
    return b

内置(25000次操作时4.69秒):

def max2(a, b):
    return max(a, b)

无分支1(25000次操作4.12秒):

def max3(a, b):
    return (a > b) * a + (a <= b) * b

无分支2(25000次操作5.34秒):

def max4(a, b):
    diff = a - b
    return a - (diff & diff >> 31)

推荐答案

您对分支代码与无分支代码的期望适用于汇编和C等低级语言.在低级语言中,无分支代码可以更快,因为它可以防止分支预测失误导致的速度减慢.(注意:这意味着无分支代码can会更快,但不一定会更快.)

Python是一种高级语言.假设您使用的是CPython解释器:对于您执行的每一条字节码指令,解释器都必须在操作码类型上进行分支,通常还有许多其他事情.例如,即使是简单的<运算符也需要一个分支来判断<操作码,另一个分支来判断对象的类是否实现了__lt__方法,更多分支来判断右侧值是否是要执行比较的有效类型,可能还需要几个其他分支.由于这些原因,即使是所谓的"无分支"代码在实践中也会导致大量分支.

由于Python是如此高级,与单个机器代码指令相比,每个字节码指令实际上都做了大量的工作.因此,像这样的简单代码的性能主要取决于需要解释多少字节码指令:

  • max1函数必须执行三次局部变量加载:比较、条件跳转和返回.一共六个.
  • max2函数执行两次局部变量加载,一次全局变量加载(参考内置max),还进行函数调用;这需要传递参数,与其他字节码指令相比成本相对较高.除此之外,内置函数本身必须做与您自己的max1函数相同的工作,所以难怪max2要慢一些.
  • max3函数执行六次局部变量加载、两次比较、两次乘法、一次加法和一次返回.这是12条指令,所以我们预计它需要的时间大约是max1条指令的两倍.
  • 同样地,max4会加载五个局部变量,一个存储到局部变量,一个常量,两个减法,一个位移位,一个按位"and",以及一个返回.这又是12条指令.

也就是说,请注意,如果我们直接将max1与内置函数max进行比较,而不是将max2进行额外的函数调用,那么max1函数仍然比内置函数maxa bit faster.这可能是因为内置max接受数量可变的参数,这可能涉及构建一个参数元组,而内置max函数还有一个分支,用于判断是否使用单个iterable参数(例如max([3, 1, 4, 2]))调用它,并以不同的方式处理该情况;你的max1函数不能做这些事情.

Python相关问答推荐

如何在BeautifulSoup中链接Find()方法并处理无?

如何自动抓取以下CSV

使用FASTCGI在IIS上运行Django频道

scikit-learn导入无法导入名称METRIC_MAPPING64'

无法通过python-jira访问jira工作日志(log)中的 comments

如何请求使用Python将文件下载到带有登录名的门户网站?

将9个3x3矩阵按特定顺序排列成9x9矩阵

海上重叠直方图

Flask Jinja2如果语句总是计算为false&

为什么常规操作不以其就地对应操作为基础?

通过追加列表以极向聚合

在Python中控制列表中的数据步长

什么是一种快速而优雅的方式来转换一个包含一串重复的列,而不对同一个值多次运行转换,

jsonschema日期格式

有没有办法在不先将文件写入内存的情况下做到这一点?

将数字数组添加到Pandas DataFrame的单元格依赖于初始化

将Pandas DataFrame中的列名的长文本打断/换行为_STRING输出?

如何通过函数的强式路径动态导入函数?

如何在微调Whisper模型时更改数据集?

如何使用count()获取特定日期之间的项目