不是,我有50GB的数据集另存为h5py,这是其中的字典。字典包含从0到n的键,值是numpy ndarray(3维),具有相同的形状。例如:
dictionary [0] = np.array([[[...],[...]] ...])
我想连接所有这些np数组,像这样的代码
sample = np.concatenate(list(dictionary.values))
此操作浪费100GB内存!如果我使用
del dictionary
它将减少到50GB内存。但是我想在加载数据时将内存使用控制为50GB。我尝试过的另一种方式
sample = np.concatenate(sample,dictionary[key])
它仍在使用100GB内存。我认为以上所有情况,右侧都会创建一个要保存的新内存块,然后分配给左侧,这将在计算期间将内存增加一倍。因此,我尝试这样的第三种方式
sample = np.empty(shape)
with h5py.File(...) as dictionary:
for key in dictionary.keys():
sample[key] = dictionary[key]
我认为这段代码有一个优势。将值dictionary [key]分配给样本的某一行,然后会清除dictionary [key]的内存。但是,我对其进行了测试,发现内存使用量也为100GB。为什么?
是否有任何好的方法将内存使用量限制为50GB?
答案 0 :(得分:1)
您的问题是您需要在内存中存储2个相同数据的副本。
如果像test1
中那样构建数组,则一次需要的内存要少得多,但是会丢失字典。
import numpy as np
import time
def test1(n):
a = {x:(x, x, x) for x in range(n)} # Build sample data
b = np.array([a.pop(i) for i in range(n)]).reshape(-1)
return b
def test2(n):
a = {x:(x, x, x) for x in range(n)} # Build sample data
b = np.concatenate(list(a.values()))
return b
x1 = test1(1000000)
del x1
time.sleep(1)
x2 = test2(1000000)
结果:
test1 : 0.71 s
test2 : 1.39 s
第一次测试是针对test1的,虽然位置不正确,但是可以大大降低内存使用量。
答案 1 :(得分:0)
SELECT DISTINCT Id, ColumnId, (SELECT MAX(Type) FROM blog) AS type
FROM Blog
是文件上的数据集。 dictionary[key]
将是一个numpy数组,该数据集已下载。
我想像
dictionary[key][...]
被评估为
sample[key] = dictionary[key]
下载数据集,然后将其复制到sample[key,...] = dictionary[key][...]
数组的一部分。该下载的阵列应免费回收。但是是否numpy / python这样做是另一回事。我不习惯提高内存限制。
您不想执行增量连接-这很慢。列表上的单个串联应该更快。我不知道为什么这样
sample
包含。它是对数据集或下载的数组的引用吗?无论该列表上的list(dictionary.values)
,都必须使用下载的阵列。
有一件事使我感到困惑-您如何使用相同的concatenate(...)
来索引key
的第一维和sample
中的数据集? dictionary
键应该是字符串,而不是整数。
一些测试
请注意,我正在使用字符串数据集名称:
h5py
您的In [21]: d = f.create_dataset('0',data=np.zeros((2,3)))
In [22]: d = f.create_dataset('1',data=np.zeros((2,3)))
In [23]: d = f.create_dataset('2',data=np.ones((2,3)))
In [24]: d = f.create_dataset('3',data=np.arange(6.).reshape(2,3))
代码丢失了np.concatenate(list(dictionary.values))
:
()
因此,这只是数据集的列表。当In [25]: f.values
Out[25]: <bound method MappingHDF5.values of <HDF5 file "test.hf" (mode r+)>>
In [26]: f.values()
Out[26]: ValuesViewHDF5(<HDF5 file "test.hf" (mode r+)>)
In [27]: list(f.values())
Out[27]:
[<HDF5 dataset "0": shape (2, 3), type "<f8">,
<HDF5 dataset "1": shape (2, 3), type "<f8">,
<HDF5 dataset "2": shape (2, 3), type "<f8">,
<HDF5 dataset "3": shape (2, 3), type "<f8">]
对列表的每个元素执行concatenate
时,就会进行下载:
np.asarray(a)
例如:
In [28]: np.concatenate(list(f.values()))
Out[28]:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.],
[0., 1., 2.],
[3., 4., 5.]])
让我们看看使用迭代方法时会发生什么:
制作一个可以为每个“行”取一个数据集的数组:
In [29]: [np.array(a) for a in f.values()]
Out[29]:
[array([[0., 0., 0.],
[0., 0., 0.]]), array([[0., 0., 0.],
[0., 0., 0.]]), array([[1., 1., 1.],
[1., 1., 1.]]), array([[0., 1., 2.],
[3., 4., 5.]])]
In [30]: [a[...] for a in f.values()]
....
在这个小例子中,它回收了其他所有数据缓冲区块。第2次迭代释放了第一个迭代中使用的数据缓冲区,然后可以在第3个迭代中重复使用,依此类推。
这些是交互式In [34]: samples = np.zeros((4,2,3),float)
In [35]: for i,d in enumerate(f.values()):
...: v = d[...]
...: print(v.__array_interface__['data']) # databuffer location
...: samples[i,...] = v
...:
(27845184, False)
(27815504, False)
(27845184, False)
(27815504, False)
In [36]: samples
Out[36]:
array([[[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.]],
[[0., 1., 2.],
[3., 4., 5.]]])
会话中的小数组。我不知道这些观察是否适用于大案子。