numpy.dot - > MemoryError,my_dot - >非常慢,但有效。为什么?

时间:2014-12-27 15:02:41

标签: python arrays numpy

我正在尝试计算两个分别为(162225,10000)和(10000,100)大小的numpy数组的点积。但是,如果我调用numpy.dot(A,B),就会发生MemoryError。 然后,我试着编写我的实现:

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)我如何规避/解决问题?

我在64位配备的计算机上使用Python 3.4.2(64位)和Numpy 1.9.1,运行Ubuntu 14.10的16GB内存。

2 个答案:

答案 0 :(得分:2)

您收到内存错误的原因可能是因为numpy正在尝试将一个或两个数组复制到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。通常,只要一切都适合内存,较大的块大小就会更快。

答案 1 :(得分:1)

我认为问题从矩阵A本身开始,因为如果每个元素是双精度浮点数,16225 * 10000大小矩阵已经占用了大约12GB的内存。这与numpy如何创建临时副本以进行点操作一起将导致错误。额外的副本是因为numpy使用底层的BLAS操作来完成点,这需要将矩阵存储在连续的C顺序中

如果您想要更多关于改善网络效果的讨论,请查看这些链接

http://wiki.scipy.org/PerformanceTips

Speeding up numpy.dot

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