NumPy的数学函数比Python的快吗?

69

我有一个由基本数学函数(abs、cosh、sinh、exp等)组合定义的函数。

我想知道使用 numpy.abs() 而不是 abs() 是否会在速度上有所差异?


14
使用timeit - Humphrey Bogart
2
没有 math.abs()。我猜你是指 abs() - Eric O. Lebigot
@EOL 是的,抱歉,我编辑了问题。谢谢。 - Mermoz
3个回答

88

这里是时间结果:

lebigot@weinberg ~ % python -m timeit 'abs(3.15)' 
10000000 loops, best of 3: 0.146 usec per loop

lebigot@weinberg ~ % python -m timeit -s 'from numpy import abs as nabs' 'nabs(3.15)'
100000 loops, best of 3: 3.92 usec per loop

numpy.abs()abs()慢,因为它还处理Numpy数组:它包含额外的代码以提供此灵活性。

然而,对于数组,Numpy确实很快:

lebigot@weinberg ~ % python -m timeit -s 'a = [3.15]*1000' '[abs(x) for x in a]'
10000 loops, best of 3: 186 usec per loop

lebigot@weinberg ~ % python -m timeit -s 'import numpy; a = numpy.empty(1000); a.fill(3.15)' 'numpy.abs(a)'
100000 loops, best of 3: 6.47 usec per loop

(PS: '[abs(x) for x in a]'在Python 2.7中比更好的map(abs, a)要慢,后者快约30%,但仍然比NumPy慢得多。)

因此,对于1000个元素而言,numpy.abs()所需的时间与1个单独的浮点数差别不大!


6
很不错,如果能够得到运行命令 "python -m timeit -s 'import numpy' -s 'a=numpy.array((1,)*1000)' 'numpy.abs(a)'" 的结果将非常好,这可以展示 NumPy 的数组在速度方面的优势。 - BatchyX
6
似乎你的timeit包括导入numpy,仅导入numpy就需要几秒钟时间。此外,在你的第二个示例中,我想知道Python基本的"abs"函数花费的时间是否更多来自于列表推导式而不是"abs"函数本身? - tbhartman
15
请注意在 timeit 命令中给出的 -s 选项:import numpy 实际上只在 设置 期间执行了 一次,并不会计时。至于 abs() 的示例,用 x 替换 abs(x) 后可以看出 abs() 使用了一半的总运行时间。无论如何,重点仍然相同:与纯(CPython 解释的)Python 相比,NumPy 真的非常快。 - Eric O. Lebigot

25

您应该使用numpy函数来处理numpy的类型,使用常规python函数来处理常规python类型。

最差的性能通常出现在混合使用python内置类型和numpy时,因为需要进行类型转换。虽然这些类型转换已经得到了优化,但不使用它们通常仍然更好。当然,效果因人而异,所以请使用分析工具来找出最佳方案。

此外,考虑使用像cython这样的程序或制作C模块,如果您想进一步优化程序。或者在性能要求高时不使用python。

但是,当您的数据被放入numpy数组中时,numpy可以非常快地计算大量数据。


9
事实上,在numpy数组中,内置的abs通过__abs__调用了numpy的实现,详见为什么内置函数如abs在numpy数组上有效?。因此,理论上性能差异不应该很大。
import timeit
 
x = np.random.standard_normal(10000)
 
def pure_abs():
    return abs(x)
 
def numpy_abs():
    return np.abs(x)
 
n = 10000
 
t1 = timeit.timeit(pure_abs, number = n)
print('Pure Python abs:', t1)
t2 = timeit.timeit(numpy_abs, number = n)
print('Numpy abs:', t2)
Pure Python abs: 0.435754060745
Numpy abs: 0.426516056061

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接