首先,您的示例很奇怪,因为apply_over_axis
在一维数组上只会将整个数组作为单个参数传递。它不会为每个元素重复调用。为此,您想要vectorize
.
不过,更一般地说,numpy 并不能真正加速任意 Python 函数的应用。numpy 的主要优点是它提供了自己的许多数学函数的实现,而且速度很快。它不能神奇地发挥任何功能,只是让它运行得更快。
此外,您的示例并不完全平行。一方面,您不会在两者中调用相同的函数。更具体地说,您的测试都包括在定时测试中创建输入——也就是说,您在测试的定时部分中创建xrange(100)
和内部。np.arange(100)
因此,您正在测量的部分内容是创建 Numpy 数组比创建xrange
对象要慢:
>>> timeit.timeit("np.arange(100)", "import numpy as np")
0.95243776
>>> timeit.timeit("xrange(100)", "import numpy as np")
0.2129926399999995
这大约是 5 倍。但是在实际应用程序中,您几乎可以肯定已经创建了输入数组,因此这不是一个现实的测试。
使用并行测试,我发现普通列表版本的速度只有大约两倍:
def doNothing(crud):
return crud
>>> timeit.timeit("np.vectorize(doNothing)(thing)", "import numpy as np; from __main__ import doNothing; thing = np.arange(100)")
49.13036320000003
>>> timeit.timeit("[doNothing(x) for x in thing]", "import numpy as np; from __main__ import doNothing; thing = np.arange(100)")
25.873566400000072
此外,如果您应用的是 numpy 函数,则 numpy 版本可以更快:
>>> timeit.timeit("np.log(thing)", "import numpy as np; import math; from __main__ import doNothing; thing = np.arange(100)+1")
3.2039433600000393
>>> timeit.timeit("[math.log(x) for x in thing]", "import numpy as np; import math; from __main__ import doNothing; thing = np.arange(100)+1")
37.74219519999997
这个故事的寓意是 numpy 真的是 NUMpy——它是为进行数值计算而设计的,并且它具有快速计算的功能。这不仅仅是加速你所有循环的东西。如果您只是有大量对象要对其应用任意函数,那么 numpy 不太可能加快您的代码速度,甚至可能减慢它的速度。(它对于非数字数据仍然非常有用,因为它对多维数组的复杂索引等功能很方便,并且可能比使用嵌套列表等的等效 Python 结构更快。它只是对加速循环没有用处这些结构。)