我试图对4D图像阵列(包括时间序列)做简单的计算,但是与初始化的数组相比,广播占用了大量的RAM,而且我已经尝试用一些类似的问题来读取其他内存。例如Memory growth with broadcast operations in NumPy
在这里,来自"rth“的评论说:”广播不为初始数组分配额外的内存“。
“Weckesser”所接受的评论显示了提问者使用og newaxis来创建额外的分配数组的问题。
我试着做沃伦展示的东西,但是我仍然被大量的内存消耗掉,我不知道为什么。现在,我已经实现了rths块计算方法,并取得了很好的结果,但它仍然困扰着我,为什么直接的numpy计算会在RAM的使用中崩溃。
这里是我所做的事情的一个例子,
我初始化了将数据添加到其中的数组,并创建了uint16的随机原始图像,因为它来自带有12位原始图像数据的16位TIFF文件。我保留其余的float32来保存内存。最后的精度没那么重要
import numpy as np
imagearraydensity = np.ones((512, 1024, 250, 20),dtype=np.float32)
imagearrayraw = np.random.randint(4095,size=(512, 1024, 250, 20),dtype=np.uint16)我手上有两个线性常数数组,这里只是随机数。
acons = np.random.random((512, 1024)).astype(np.float32)
bcons = np.random.random((512, 1024)).astype(np.float32)然后计算
np.divide(np.subtract(imagearrayraw, bcons[:, :, np.newaxis, np.newaxis], dtype=np.float32),
acons[:, :, np.newaxis, np.newaxis],
imagearraydensity, # Output array position
dtype=np.float32)当计算完成时,我的实际数据代码将在我的系统上使用~ 36 GB的RAM和~27 GB的内存。
我能做些什么来减少直接广播对RAM的使用吗?还是像我已经实现的那样,基于块的方法是最好的方法?
发布于 2022-02-18 17:20:31
首先,两个输入数组包含2_621_440_000项,从而产生15 GiB的内存。由np.subtract生成的临时数组包含相同数量的元素,从而产生10 GiB的内存。输出数组被覆盖,因此不应该占用更多的RAM。这意味着Numpy应该已经占用了25 GiB的内存。
问题是,Numpy不知道如何从uint16数组中减去float32数组。因此,它应用了导致uint16 数组被抛给数组的semantic rules。这意味着它创建了一个新的10 GiB临时数组,从而占用了内存的~36 GiB。注意,Numpy和Python都不是为了最小化内存占用而设计的。
尽管如此,解决这一问题有几个解决办法。一种解决方案是将输入数据分割成块,以便临时数组占用更少的空间。这件事做起来很麻烦。另一个理论上的解决方案是自己转换数组,以便用imagearrayraw编写它,但是Numpy没有为astype提供一个out参数。另一种解决方案是使用Numba以便执行强制执行(这是更有效的)。
以下是基于块的解决方案:
for i in range(imagearraydensity.shape[0]):
imagearraydensity[i,...] = imagearrayraw[i,...].astype(np.float32)
np.subtract(imagearraydensity, bcons[:, :, np.newaxis, np.newaxis], out=imagearraydensity, dtype=np.float32)
np.divide(imagearraydensity, acons[:, :, np.newaxis, np.newaxis], out=imagearraydensity, dtype=np.float32)这个解决方案在我的机器上需要15 GiB。
https://stackoverflow.com/questions/71174542
复制相似问题