问题 NumPy中行与列操作的性能


几篇文章 这表明MATLAB更喜欢列操作而不是行操作,这取决于您将数据布置在性能上 可以变化很大。这显然是因为MATLAB使用了 列优先 表示数组的顺序。

我记得读过Python(NumPy)使用的 行主 订购。有了这个,我的问题是:

  1. 在使用NumPy时,可以预期性能会有类似的差异吗?
  2. 如果上面的答案是肯定的,那会是什么 突出这种差异的例子

10679
2017-07-30 18:48


起源

你可能想看看 这个。这是最近的例子,其中不同轴上的操作存在很大差异。虽然这可能是一个错误。 - Daniel


答案:


像许多基准一样,这实际上取决于具体情况。确实,默认情况下,numpy以C连续(行 - 主)顺序创建数组,因此,在抽象中,扫描列的操作应该比扫描行的操作快。但是,阵列的形状,ALU的性能以及处理器上的底层高速缓存对细节产生巨大影响。

例如,在我的MacBook Pro上,使用小整数或浮点数组,时间类似,但小整数类型明显慢于浮点类型:

>>> x = numpy.ones((100, 100), dtype=numpy.uint8)
>>> %timeit x.sum(axis=0)
10000 loops, best of 3: 40.6 us per loop
>>> %timeit x.sum(axis=1)
10000 loops, best of 3: 36.1 us per loop

>>> x = numpy.ones((100, 100), dtype=numpy.float64)
>>> %timeit x.sum(axis=0)
10000 loops, best of 3: 28.8 us per loop
>>> %timeit x.sum(axis=1)
10000 loops, best of 3: 28.8 us per loop

对于较大的阵列,绝对差异会变大,但对于较大的数据类型,至少在我的机器上仍然较小:

>>> x = numpy.ones((1000, 1000), dtype=numpy.uint8)
>>> %timeit x.sum(axis=0)
100 loops, best of 3: 2.36 ms per loop
>>> %timeit x.sum(axis=1)
1000 loops, best of 3: 1.9 ms per loop

>>> x = numpy.ones((1000, 1000), dtype=numpy.float64)
>>> %timeit x.sum(axis=0)
100 loops, best of 3: 2.04 ms per loop
>>> %timeit x.sum(axis=1)
1000 loops, best of 3: 1.89 ms per loop

您可以告诉numpy使用。创建一个Fortran连续(列主要)数组 order='F' 关键字参数 numpy.asarraynumpy.onesnumpy.zeros等等,或者通过使用转换现有数组 numpy.asfortranarray。正如预期的那样,这种排序交换了行或列操作的效率:

in [10]: y = numpy.asfortranarray(x)
in [11]: %timeit y.sum(axis=0)
1000 loops, best of 3: 1.89 ms per loop
in [12]: %timeit y.sum(axis=1)
100 loops, best of 3: 2.01 ms per loop

11
2017-07-30 20:11





In [38]: data = numpy.random.rand(10000,10000)

In [39]: %timeit data.sum(axis=0)
10 loops, best of 3: 86.1 ms per loop

In [40]: %timeit data.sum(axis=1)
10 loops, best of 3: 101 ms per loop

2
2017-07-30 19:37





我怀疑它会因数据和操作而有所不同。

简单的答案是使用相同的,真实世界,您计划使用的排序数据以及您计划使用的功能编写一些测试,然后使用 cprofile 要么 timeit 比较您的操作速度,具体取决于您的数据结构。


0
2017-07-30 18:57