- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在计时 enumerate
时注意到以下奇怪行为使用指定的默认 start
参数:
In [23]: %timeit enumerate([1, 2, 3, 4])
The slowest run took 7.18 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 511 ns per loop
In [24]: %timeit enumerate([1, 2, 3, 4], start=0)
The slowest run took 12.45 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 1.22 µs per loop
因此,对于指定 start
的情况,速度大约降低 2 倍。
为每种情况发布的字节代码并没有真正表明任何会导致速度显着差异的内容。一个恰当的例子,在用 dis.dis
检查了不同的调用之后发出的附加命令是:
18 LOAD_CONST 5 ('start')
21 LOAD_CONST 6 (0)
这些以及具有 1 个关键字的 CALL_FUNCTION
是唯一的区别。
我尝试跟踪 CPython
中的调用 ceval
使用 gdb
并且两者似乎都使用 do_call
在 call_function
中,而不是我能检测到的其他优化。
现在,我明白 enumerate
只是创建一个枚举迭代器,所以我们在这里处理对象创建(对吧?)。我查看了 Objects/enumobject.c
如果指定了 start
,则尝试发现任何差异。唯一(我相信)不同的是当 start != NULL
时会发生以下情况:
if (start != NULL) {
start = PyNumber_Index(start);
if (start == NULL) {
Py_DECREF(en);
return NULL;
}
assert(PyInt_Check(start) || PyLong_Check(start));
en->en_index = PyInt_AsSsize_t(start);
if (en->en_index == -1 && PyErr_Occurred()) {
PyErr_Clear();
en->en_index = PY_SSIZE_T_MAX;
en->en_longindex = start;
} else {
en->en_longindex = NULL;
Py_DECREF(start);
}
这看起来不像是会引入 2 倍减速的东西。 (我想,不确定。)
前面的代码段已在 Python 3.5
上执行,不过在 2.x
中也有类似的结果。
这是我被困住的地方,不知道该往哪里看。这可能只是第二种情况下额外调用累积的开销的情况,但同样,我不太确定。 有人知道这背后的原因是什么吗?
最佳答案
一个原因可能是调用了 PyNumber_Index
当您在以下部分指定开始时:
if (start != NULL) {
start = PyNumber_Index(start);
如果你看一下 abstract.c
中的 PyNumber_Index
函数模块,您将在函数的顶层看到以下注释:
/* Return a Python int from the object item.
Raise TypeError if the result is not an int
or if the object cannot be interpreted as an index.
*/
所以这个函数必须检查对象是否不能被解释为索引并返回相关错误。如果您仔细查看源代码,您会看到所有这些检查和引用,特别是在以下部分,它必须执行嵌套结构取消引用以检查索引类型:
result = item->ob_type->tp_as_number->nb_index(item);
if (result &&
!PyInt_Check(result) && !PyLong_Check(result)) {
...
检查并返回所需结果会花费很多时间。
但正如@user2357112 提到的,另一个也是最重要的原因是因为 python 关键字参数匹配。
如果您对不带关键字参数的函数进行计时,您会看到差异时间将减少大约 2 倍时间:
~$ python -m timeit "enumerate([1, 2, 3, 4])"
1000000 loops, best of 3: 0.251 usec per loop
~$ python -m timeit "enumerate([1, 2, 3, 4],start=0)"
1000000 loops, best of 3: 0.431 usec per loop
~$ python -m timeit "enumerate([1, 2, 3, 4],0)"
1000000 loops, best of 3: 0.275 usec per loop
与位置参数的区别在于:
>>> 0.251 - 0.275
-0.024
这似乎是因为 PyNumber_Index
。
关于python - 为什么在不指定关键字start时枚举执行速度较慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34676913/
有人可以解释一下,在 DOM 中搜索元素时,为什么 Xpath 被认为比 CSS 选择器慢。不同的选择器是否有不同的引擎(例如 Xpath、CSS 选择器等) 谢谢 最佳答案 Xpath 并不是被认为
在我们的一个 MVC 页面中尝试加速某些 ajax 调用时,我遇到了一些我无法真正解释的奇怪行为。我每隔 N 秒就会进行一些 ajax 调用,以轮询一些统计数据。 似乎在物理上不同的文件中对 Cont
Background 尝试进行一个简单的实验,看看传统的 if 语句检查 null 是否比 Apache Commons Lang StringUtils isEmpty/isBlank 更快。 为了
我正在从 Android 设备调用 rest api,并且看到与 PC 相比的速度差异,我感到非常惊讶。下面是来自 PC 上的休息工具的图像。 我尝试了几个库,如 Retrofit、Volley 和常
为什么 scipy.distance.cdist 使用 float32 和 float64 时性能差异很大? from scipy.spatial import distance import num
我是一名优秀的程序员,十分优秀!