【发布时间】:2017-02-03 15:25:20
【问题描述】:
@Dunes 的 answer 指出,由于流水线化,浮点乘法和除法之间(几乎)没有区别。但是,根据我对其他语言的经验,我预计该部门会变慢。
我的小测试如下:
A=np.random.rand(size)
command(A)
对于不同的命令和size=1e8,我在我的机器上得到以下时间:
Command: Time[in sec]:
A/=0.5 2.88435101509
A/=0.51 5.22591209412
A*=2.0 1.1831600666
A*2.0 3.44263911247 //not in-place, more cache misses?
A+=A 1.2827270031
最有趣的部分:除以0.5 的速度几乎是除以0.51 的两倍。可以假设,这是由于一些智能优化,例如用A+A 替换除法。但是A*2 和A+A 的时间太远了,无法支持这种说法。
一般来说,值(1/2)^n 的浮点数除法更快:
Size: 1e8
Command: Time[in sec]:
A/=0.5 2.85750007629
A/=0.25 2.91607499123
A/=0.125 2.89376401901
A/=2.0 2.84901714325
A/=4.0 2.84493684769
A/=3.0 5.00480890274
A/=0.75 5.0354950428
A/=0.51 5.05687212944
如果我们看一下size=1e4,它会变得更有趣:
Command: 1e4*Time[in sec]:
A/=0.5 3.37723994255
A/=0.51 3.42854404449
A*=2.0 1.1587908268
A*2.0 1.19793796539
A+=A 1.11329007149
现在,除以.5 和除以.51 之间没有区别!
我针对不同的 numpy 版本和不同的机器进行了尝试。在某些机器上(例如 Intel Xeon E5-2620)可以看到这种效果,但在其他一些机器上看不到 - 这与 numpy 版本无关。
使用@Ralph Versteegen 的脚本(请参阅他的精彩回答!)我得到以下结果:
- i5-2620 的时序(Haswell,2x6 内核,但不使用 SIMD 的非常旧的 numpy 版本):
- i7-5500U(Broadwell,2 核,numpy 1.11.2)的时序:
问题是:如果数组大小很大(>10^6 )。
@nneonneo 的回答指出,对于某些英特尔处理器,除以 2 的幂时存在优化,但这并不能解释为什么我们只能看到它对大型阵列的好处。
最初的问题是“如何解释这些不同的行为(0.5 与0.51 的划分)?”
这里也是我的原始测试脚本,它产生了时间:
import numpy as np
import timeit
def timeit_command( command, rep):
print "\t"+command+"\t\t", min(timeit.repeat("for i in xrange(%d):"
%rep+command, "from __main__ import A", number=7))
sizes=[1e8, 1e4]
reps=[1, 1e4]
commands=["A/=0.5", "A/=0.51", "A*=2.2", "A*=2.0", "A*2.2", "A*2.0",
"A+=A", "A+A"]
for size, rep in zip(sizes, reps):
A=np.random.rand(size)
print "Size:",size
for command in commands:
timeit_command(command, rep)
【问题讨论】:
-
你的基准是什么?算术速度还是解释器效率?
-
@Yves 我的目标是对算术速度进行基准测试,但我不确定我在现实中的基准测试是什么
-
我无法重现 0.5 和 0.51 之间的除法差异。无论数组大小如何,在 IPython 中使用
%timeit魔法似乎都需要相同的时间。 -
@Laleh 适用于整数值,是否也适用于浮点值?
-
@ajcr 在另一台具有较新硬件的机器上我也看不出
0.5和0.51之间的区别:(
标签: python performance numpy