我想在Python中创建一个空的Numpy数组,以便以后用值填充它。下面的代码生成一个具有2个字节整数的1024x1024x1024数组,这意味着它应该在RAM中至少占用2GB。
>>> import numpy as np; from sys import getsizeof
>>> A = np.zeros((1024,1024,1024), dtype=np.int16)
>>> getsizeof(A)
2147483776
从getsizeof(A)
中,我们看到该数组占用2 ^ 31 + 128字节(可能是标题信息)。但是,使用任务管理器,我可以看到 Python仅占用18.7 MiB的内存
假定数组已压缩,我为每个内存插槽分配了随机值,以使它不能被压缩。
>>> for i in range(1024):
... for j in range(1024):
... for k in range(1024):
... A[i,j,k] = np.random.randint(32767, dtype = np.int16)
循环仍在运行,并且我的RAM正在缓慢增加(大概是因为数组组成A膨胀并带有难以理解的噪声。)我假设这样做会使我的代码更快,迫使numpy从一开始就扩展此数组。奇怪的是,我还没有在任何地方看到此文件!
因此,1.为什么numpy这样做?和2.如何强制numpy分配内存?
答案 0 :(得分:0)
让我们看一下较小情况下的一些时间安排:
In [107]: A = np.zeros(10000,int)
In [108]: for i in range(A.shape[0]): A[i]=np.random.randint(327676)
我们无需制作A
3d即可获得相同的效果;总尺寸相同的1d就好。
In [109]: timeit for i in range(A.shape[0]): A[i]=np.random.randint(327676)
37 ms ± 133 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
现在将这段时间与一次调用生成随机数的方法进行比较:
In [110]: timeit np.random.randint(327676, size=A.shape)
185 µs ± 905 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
快得多。
如果我们执行相同的循环,但只需将随机数分配给变量(并将其丢弃):
In [111]: timeit for i in range(A.shape[0]): x=np.random.randint(327676)
32.3 ms ± 171 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
时间几乎与原始情况相同。将值分配给zeros
数组并不是大的时间消耗。
我没有像您一样测试很大的情况,并且我的A
已经被完全初始化。因此,欢迎您重复比较您的尺寸。但是我认为该模式仍然适用-迭代1024x1024x1024次(比我的示例大10万次)是大量的时间消耗,而不是内存分配任务。
您可能会尝试的其他方法:仅对A
的第一个维度进行迭代,然后分配形状类似于其他两个维度的randomint
。例如,将我的A
的尺寸扩展为10:
In [112]: A = np.zeros((10,10000),int)
In [113]: timeit for i in range(A.shape[0]): A[i]=np.random.randint(327676,size=A.shape[1])
1.95 ms ± 31.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
A
比[107]中的大10倍,但填充时间却减少了16倍,因为它只会迭代10倍。在numpy
中,如果必须进行迭代,请尝试对更复杂的任务进行几次。
({timeit
重复测试多次(例如7 * 10),因此即使我使用足够大的数组,它也不会捕获任何初始内存分配步骤)。 / p>