python 调用函数 开销_为什么Python代码在函数中运行得更快?

除了本地/全局变量存储时间之外,操作码预测使功能更快。

正如其他答案所解释的,该函数使用STORE_FAST循环中的操作码。下面是函数循环的字节码:>>   13 FOR_ITER                 6 (to 22)   # get next value from iterator

16 STORE_FAST               0 (x)       # set local variable

19 JUMP_ABSOLUTE           13           # back to FOR_ITER

通常,当程序运行时,Python会一个接一个地执行每个操作码,跟踪堆栈,并在每个操作码执行后预先对堆栈帧进行其他检查。Opcode预测意味着在某些情况下Python能够直接跳转到下一个操作代码,从而避免了一些开销。

在这种情况下,每次Python看到FOR_ITER(循环的顶部),它将“预测”STORE_FAST是它必须执行的下一个操作码。Python然后窥视下一个操作码,如果预测是正确的,它直接跳到STORE_FAST..这样做的效果是将这两个操作码压缩成一个操作码。

另一方面,STORE_NAME在全局级别的循环中使用操作码。Python做*不是*当它看到这个操作码时做类似的预测。相反,它必须回到计算循环的顶部,这对循环的执行速度有明显的影响。

为了给出更多关于优化的技术细节,下面引用ceval.c文件(Python虚拟机的“引擎”):一些操作码往往成对出现,从而使得在第一个代码运行时能够预测第二个代码。例如,GET_ITER经常跟在后面FOR_ITER..和FOR_ITER经常跟在后面STORE_FAST或UNPACK_SEQUENCE.

验证预测需要对一个常量对寄存器变量进行一次高速测试.如果配对是好的,那么处理器自己的内部分支预测很有可能成功,从而导致向下一个操作码的几乎零开销转换。成功的预测保存了遍历val循环的行程,包括它的两个不可预测的分支,即HAS_ARG测试和开关箱。结合处理器的内部分支预测,一个成功的PREDICT这两个操作码的运行效果就好像它们是一个单一的新操作码,并将其与身体结合在一起。

我们可以在源代码中看到FOR_ITER操作码,准确地预测到STORE_FAST现制作:case FOR_ITER:                         // the FOR_ITER opcode case

v = TOP();

x = (*v->ob_type->tp_iternext)(v); // x is the next value from iterator

if (x != NULL) {

PUSH(x);                       // put x on top of the stack

PREDICT(STORE_FAST);           // predict STORE_FAST will follow - success!

PREDICT(UNPACK_SEQUENCE);      // this and everything below is skipped

continue;

}

// error-checking and more code for when the iterator ends normally

这个PREDICT功能扩展到if (*next_instr == op) goto PRED_##op也就是说,我们只是跳到预测操作码的开始。在这种情况下,我们跳到这里:PREDICTED_WITH_ARG(STORE_FAST);case STORE_FAST:

v = POP();                     // pop x back off the stack

SETLOCAL(oparg, v);            // set it as the new local variable

goto fast_next_opcode;

现在设置局部变量,并开始执行下一个操作码。Python继续遍历可迭代直到它到达终点,每次都做出成功的预测。

这个Python wiki页面拥有有关CPython虚拟机工作方式的更多信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值