2013-07-30 47 views
11

a few articles表明MATLAB比列操作更喜歡列操作,並且根據您的佈局,數據的性能爲can vary significantly。這顯然是因爲MATLAB使用column-major順序來表示數組。NumPy中行與列操作的性能

我記得讀到Python(NumPy)使用row-major命令。有了這個,我的問題是:

  1. 在使用NumPy的時候,性能會有什麼差別嗎?
  2. 如果上面的答案是肯定的,那麼的幾個例子會突出顯示這種差異
+0

您可能想查看[this](http://stackoverflow.com/questions/17840661)。這是最近的一個例子,在不同軸上的操作有很大差異。儘管這可能是一個錯誤。 – Daniel

回答

11

像許多基準一樣,這真的取決於具體的情況。確實,默認情況下,numpy會創建C-contiguous(row-major)順序的數組,因此在抽象中,掃描列的操作應該比掃描行的操作更快。但是,陣列的形狀,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的使用order='F'關鍵字參數創建一個Fortran連續(列爲主)陣列numpy.asarraynumpy.ones,numpy.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 
0

我懷疑它會根據數據和操作而有所不同。

簡單的答案是使用相同的真實世界,您正在計劃使用的排序數據以及您正在計劃使用的功能編寫一些測試,然後使用cprofiletimeit來比較您的速度操作,這取決於你如何構建你的數據。

2
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