为什么numpy.ndarray.T比numpy.transpose(numpy.ndarray)快得多?

8

最近我遇到了有人使用numpy.transpose而不是numpy.ndarray.T,于是我很好奇并测试了一下时间:

from timeit import timeit
import numpy as np

array1015 = np.random.rand(10,15)

def nptrans():
    np.transpose(array1015)

def npt():
    array1015.T

print(timeit(nptrans))
print(timeit(npt))

结果如下:
np.transpose: 1.25864219666

np.ndarray.T: 0.720939874649

为什么呢?它们在底层不应该执行相同的操作吗?也许 np.transpose 执行了某种错误检查或其他减慢速度的操作?

1个回答

7

首先,操作非常快,如果有人对此进行优化,实际上并不重要!

%timeit nptrans()  # 100000 loops, best of 3: 2.11 µs per loop
%timeit npt()      # 1000000 loops, best of 3: 905 ns per loop

优化这个操作除非你要做成百万次转置操作而不进行其他操作,否则没有意义。即使添加它们也会慢得多,慢得多。

%timeit array1015 + array1015  # 100000 loops, best of 3: 3.55 µs per loop

而且,加法应该非常,非常快!

但是,在np.transpose中存在一些开销,而在np.ndarray.T中则不存在:

  • np.transpose最终调用对象的.transpose方法,这意味着它必须查找对象的方法并调用它。
  • 为了避免重复他们的代码,开发者将实际调用方法的函数打包到一个单独的函数中。=> 还需要一个函数调用。

因此,您看到的开销是2个函数调用和一个getattr调用的结果。 np.transpose函数实际上是Python,因此您可以很容易地看到这种开销(我删除了注释):

def transpose(a, axes=None):
    return _wrapfunc(a, 'transpose', axes)  # extra function call

def _wrapfunc(obj, method, *args, **kwds):
    try:
        return getattr(obj, method)(*args, **kwds)  # here it finally calls ndarray.transpose()
    except (AttributeError, TypeError):
        return _wrapit(obj, method, *args, **kwds)

我明白了。那么,问题中的代码是一个Udacity项目的神经网络,所以可能会有所不同,我需要检查一下。 - wordsforthewise

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