2

据我了解,这np.apply_over_axis是迭代 Numpy 数组的可行替代方案,因为这样做 python 方式存在瓶颈,这会使事情变慢;然而,似乎迭代需要大约 9% 的时间apply_over_axis!捎带上这篇之前的帖子,我决定为自己做一个快速的时间安排:

import numpy as np
import timeit

def triv():
     ial = [i for i in xrange(100)]

def super(fluous):
     return fluous

>>> print (timeit.timeit("triv()", setup="from __main__ import triv"))
12.3305490909
>>> print (timeit.timeit("np.apply_along_axis(super, 0, np.arange(100))", setup="from __main__ import np, super"))
130.721563921

为什么会这样?我真的不知道timeit那口井的复杂性(或者关于timeit这件事的很多事情),但我认为我的例子很简单。我想知道是否有人找到了一个好的解决方法,因为我在非常大的数组中迭代行的笛卡尔积的实际问题是如此缓慢以至于阻碍了进展。

提前致谢。

4

2 回答 2

3

首先,您的示例很奇怪,因为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 结构更快。它只是对加速循环没有用处这些结构。)

于 2013-01-21T07:27:14.847 回答
1

如果你去你的 numpy 安装目录,你可以在文件np.apply_along_axis\ma子目录中找到 python 代码extras.py

其缓慢的原因是,当它将您的函数应用于沿所选轴的数组的一维切片时,它将结果存储在数组中dtype=object并跟踪所有 return dtypes。一旦完成处理,它会选择dtype列表中最大的,并在返回之前重铸整个东西。这使它成为一个非常健壮且非常缓慢的代码。一般来说,最好避免使用numpy中的所有函数式编程例程:如果需要使用它们,最好不要使用numpy,因为速度不会有。

这并不意味着您的问题无法通过标准、快速、numpy 功能正确解决。你为什么不把它作为一个问题发布?

于 2013-01-21T07:39:17.617 回答