[在玩this question时,我注意到我无法解释np.log2
,np.log2
和np.log
的相对性能:
np.log
np.log10
比np.log10
和In [1]: %%timeit x = np.random.rand(100000)
....: np.log2(x)
....:
1000 loops, best of 3: 1.31 ms per loop
In [2]: %%timeit x = np.random.rand(100000)
np.log(x)
....:
100 loops, best of 3: 3.64 ms per loop
In [3]: %%timeit x = np.random.rand(100000)
np.log10(x)
....:
100 loops, best of 3: 3.93 ms per loop
快3倍。可能更违反直觉的是,计算ln(x + 1)的np.log2
与np.log
:
np.log10
我在numpy v1.10.1和v1.8.2。中获得了几乎相同的计时。
是否有针对这些运行时性能差异的直观解释?
我发现您的问题非常有趣,因此我花了几个小时进行一些研究;我想我已经找到了有关性能差异因为它适用于整数的解释(感谢您np.log1p(x)
的注释)-目前尚不清楚如何将推理扩展到浮点数:
[计算机使用2为基数-根据参考链接的文章,log2的计算是一个4个处理器周期的过程-log10的计算需要将log2(val)乘以1 / log2(10),这又增加了5个周期。] >
查找log2是np.log1p(x)
的问题。
位hacks:np.log2
位hacks:In [4]: %%timeit x = np.random.rand(100000)
np.log1p(x)
....:
1000 loops, best of 3: 1.46 ms per loop
整数对数10为底,首先使用上面找到对数基的技术2.通过关系log10(v)= log2(v)/ log2(10),我们需要将其乘以1 / log2(10),大约是1233/4096,即1233,然后右移12.由于IntegerLogBase2会向下舍入,因此需要添加一个。最后,由于值t只是一个近似值,可能会偏离一,通过减去v
此方法比IntegerLogBase2多执行6个操作。可能是通过修改日志加快(在具有快速内存访问权限的计算机上)上面的基于2的表查找方法,以便条目包含什么为t计算(即预加,-mulitply和-shift)。这样做总共只需要9个操作就可以找到10个对数,假设使用了4个表(v的每个字节一个)。
注意:使用DeBruijn序列查找和移位技术来计算此Matteo Italia中的log2 ((从第36分钟开始的视频)。
请注意,此StackOverflow帖子演示了finding the index of the least significant bit of a value
注意:我没有检查numpy源代码以验证它确实实现了类似的技术,但令人惊讶的是它没有实现。实际上,从OP帖子的评论中,Find integer log base 10 of an integer已检查:
实际上numpy使用glibc中的math.h,您将看到相同的区别在C / C ++中,如果您使用math.h / cmath.h。你可以找到评论很好的这两个功能的源代码,例如Find the log base 2 of an N-bit integer in O(lg(N))和MIT video: Lec 2 | MIT 6.172 Performance Engineering of Software Systems, Fall 2010–a method to make efficient log2 calculations truly cross platform with C++[9]
这只是一个注释,但长于注释。显然,这与您的特定安装有关:
免责声明:我既不是可信的,也不是官方消息来源。
(可能应该是评论,但时间太长...)