2014-12-27 97 views
3

我試圖計算兩個numpy數組分別(162225,10000)和(10000,100)大小的點積。但是,如果我調用numpy.dot(A,B)發生MemoryError。 我,然後,試着寫我的實現:numpy.dot - > MemoryError,my_dot - >非常慢,但可以工作。爲什麼?

def slower_dot (A, B): 
    """Low-memory implementation of dot product""" 
    #Assuming A and B are of the right type and size 
    R = np.empty([A.shape[0], B.shape[1]]) 
    for i in range(A.shape[0]): 
     for j in range(B.shape[1]): 
      R[i,j] = np.dot(A[i,:], B[:,j]) 
    return R 

,它工作得很好,但當然是很慢的。任何想法1)這種行爲背後的原因是什麼,2)我如何繞過/解決問題?

我在運行Ubuntu 14.10的16GB RAM的64位計算機上使用Python 3.4.2(64位)和Numpy 1.9.1。

+0

爲了清楚這一點,你在運行一個64位版本的Python嗎? – filmor 2014-12-27 15:08:00

+0

你可以試試'np.einsum'。我曾在np.dot返回內存錯誤或內存交換中斷的情況下使用它。 – hpaulj 2014-12-27 22:24:03

+0

是的,它是一個64位版本。 – marcotama 2014-12-27 23:52:47

回答

1

我認爲問題從矩陣A本身開始,因爲如果每個元素都是雙精度浮點數,則16225 * 10000大小的矩陣已經佔用大約12GB的內存。結合numpy如何創建臨時副本來執行點操作將導致錯誤。額外的副本是因爲numpy的使用潛在的BLAS操作的點,其需要的矩陣存儲在連續Ç爲了

點擊這些鏈接,如果你想了解更多有關提高點性能更加討論

http://wiki.scipy.org/PerformanceTips

Speeding up numpy.dot

https://github.com/numpy/numpy/pull/2730

+0

我發現了這個問題。 A是uint8的類型,而B是float64類型的,我相信 - 它使np.dot製作了A的副本,如您所說,它佔用了大量空間。 「解決方案」是強制機器人B和B輸入float16,這應該足夠用於我的目的 - 或者至少我希望如此:) – marcotama 2014-12-28 04:48:11

2

你得到一個內存錯誤的原因可能是因爲numpy的試圖警察y調用dot內的一個或兩個數組。對於中小型陣列來說,這通常是最有效的選擇,但對於大型陣列,您需要微觀管理numpy以避免內存錯誤。您的slower_dot函數速度很慢,主要是因爲python函數調用開銷,您將遭受162225 x 100次。當您想要平衡內存和性能限制時,以下是處理這種情況的一種常見方式。

import numpy as np 

def chunking_dot(big_matrix, small_matrix, chunk_size=100): 
    # Make a copy if the array is not already contiguous 
    small_matrix = np.ascontiguousarray(small_matrix) 
    R = np.empty((big_matrix.shape[0], small_matrix.shape[1])) 
    for i in range(0, R.shape[0], chunk_size): 
     end = i + chunk_size 
     R[i:end] = np.dot(big_matrix[i:end], small_matrix) 
    return R 

你會想挑選最適合你的特定數組大小的chunk_size。只要一切都適合內存,通常更大的塊大小將會更快。

+0

謝謝你的代碼,這不是解決了我的問題,但我希望它將有助於他人。 – marcotama 2014-12-28 04:49:42

相關問題