【问题标题】:Why is assignment operation still giving MemoryError for large arrays in Python?为什么赋值操作仍然给 Python 中的大型数组提供 MemoryError?
【发布时间】:2018-01-05 15:33:10
【问题描述】:

我有一个大数组K (29000 x 29000):

K= numpy.random.random((29000, 29000))

我想对 K 应用以下操作:

output = K* (1.5 - 0.5 * K* K)

为了尝试阻止 'MemoryError' ,我正在按照thread 的答案中的建议进行计算。

但是,当我尝试对大数组进行如下赋值操作时,我仍然得到MemoryError

K *= 1.5 - 0.5 * K * K

欢迎任何帮助。

注意:这不是重复的帖子。有一个关于这个post 使用cython 的建议。但我正在寻找可能不依赖于 Cython 的替代解决方案。

【问题讨论】:

  • 使用dask.array。在这里查看dask.pydata.org/en/latest/array.html
  • @Till Hoffman 不是重复的......这篇文章是单独发布的,目的是向更广泛的受众提出 MemoryError 的问题。感谢您使用 cython 的建议,但这篇新文章的目的是明确我当前的 MemoryError 问题,因为我正在寻找可能不依赖于 Cython 的替代解决方案。
  • 表达式1.5 - 0.5 * K * K 仍然需要创建临时数组来保存中间结果。您的阵列需要将近 7 GB。你的电脑有多少内存?
  • 也许是temp = K*K; temp *= -0.5; temp += 1.5; K *= temp; del temp。这应该避免在内存中有 3 个数组。

标签: python numpy


【解决方案1】:

您可以以块为单位进行分配,例如 1000 行。这创建的附加数组将是数组大小的 1/29,并且运行 29 次 for 循环应该不是什么速度问题。典型的内存/速度权衡。

block = 1000          # the size of row blocks to use 
K = np.random.random((29000, 29000))
for i in range(int(np.ceil(K.shape[0] / block))):
    K[i*block:(i+1)*block, :] *= 1.5 - 0.5 * K[i*block:(i+1)*block, :]**2

由于对较小矩阵的性能存在一些担忧,因此对这些矩阵进行了测试:

block = 1000
K = np.arange(9).astype(np.float).reshape((3, 3))
print(1.5 * K - 0.5 * K**3)
for i in range(int(np.ceil(K.shape[0] / block))):
    K[i*block:(i+1)*block_size, :] *= 1.5 - 0.5 * K[i*block:(i+1)*block_size, :]**2
print(K)

打印出来

[[   0.    1.   -1.]
 [  -9.  -26.  -55.]
 [ -99. -161. -244.]]

两次。

【讨论】:

  • 这是否优于上述 cmets 中 @StevenRumbalski 的答案?
  • 测试两者,你会发现。我没有你的内存/CPU 配置。
  • 建议的代码对所有数组大小(例如 30213 x 30213)都健壮吗?
  • 我会说这比@StevenRumbalski 的解决方案更好,因为在他的方法中,他多次迭代所有单元格,在这里只迭代所需的数量(基本代数几乎是免费的,甚至在 CPU 中,您可以并行执行许多计算)。另外,请考虑使用np.power(K, 2) 而不是K**2
  • @unknown121 这是一个不同的问题。如果精度足以满足您的目的,请尝试将数组转换为单精度 (np.float32)。还有memmap 可用于将数组保存在内存中的磁盘上,从而为计算中创建的临时数组释放内存。
猜你喜欢
  • 2017-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 2013-12-03
相关资源
最近更新 更多