【问题标题】:numpy.dot -> MemoryError, my_dot -> very slow, but works. Why?numpy.dot -> MemoryError, my_dot -> 很慢,但是可以。为什么?
【发布时间】:2014-12-27 15:02:40
【问题描述】:

我正在尝试计算两个大小分别为 (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)我如何规避/解决问题的任何想法?

我在运行 Ubuntu 14.10 的 64 位计算机上使用 Python 3.4.2(64 位)和 Numpy 1.9.1。

【问题讨论】:

  • 只是为了预先清除,您是否运行 64 位版本的 Python?
  • 你可以试试np.einsum。我在 np.dot 返回内存错误或因内存交换而陷入困境的情况下使用它。
  • 是的,它是 64 位版本。

标签: python arrays numpy


【解决方案1】:

您收到内存错误的原因可能是因为 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。只要所有内容都适合内存,通常较大的块大小会更快。

【讨论】:

  • 感谢您的代码,这并没有解决我的问题,但我希望它对其他人有所帮助。
【解决方案2】:

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

如果您想了解更多关于提高网点性能的讨论,请查看这些链接

http://wiki.scipy.org/PerformanceTips

Speeding up numpy.dot

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

【讨论】:

  • 我发现了问题。 A 属于 uint8 类型,而 B 属于 float64 类型,我相信这使 np.dot 复制了 A,如您所说,这占用了很多空间。 “解决方案”是强制 bot A 和 B 输入 float16,这对我的目的来说应该足够了 - 或者至少我希望如此 :)
猜你喜欢
  • 2020-04-14
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 2019-10-02
相关资源
最近更新 更多