与许多基准测试一样,这实际上取决于具体情况。确实,默认情况下,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 使用 numpy.asarray、numpy.ones、numpy.zeros 等的 order='F' 关键字参数创建一个 Fortran 连续(列主要)数组,或者通过使用转换现有数组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