gpt4 book ai didi

python - numpy array - 从磁盘逐行加载 - 内存效率高但速度快

转载 作者:太空宇宙 更新时间:2023-11-03 11:14:14 25 4
gpt4 key购买 nike

有没有办法从磁盘流水线化 numpy 数组,以这种方式保存

np.save('data.npy',np.zeros(shape=[500,300,3])) # RGB image

并以类似于生成器工作的方式逐行(或逐列)读取,但没有加载延迟?


详细说明

我的应用程序需要接近零延迟,但从磁盘加载更大的阵列可能需要一些时间(~0.02-0.1 秒)。即使是这么小的延迟也会产生不愉快的结果。

我有满足速度的解决方案:

dictionary = {'array1': array1, ....}

有了这个我可以立即访问数组,但是因为我使用的是 raspberry pi Zero,我的 python 程序受 CPU 和 RAM 的限制,所以如果我有很多数组,我会处理

MemoryError

我的应用程序以 50hz 的频率逐行读取数组,就像这样

for row in array:
[operation with row]
time.sleep(0.02) # in reality, whole cycle is 0.02s ( including operation time)

我正在寻找一种发电机:

def generate_rows(path):
array = np.load(path)
for row in array:
yield row

这解决了内存问题,但我猜想我将失去接近零的延迟(加载数组)。

因此我的问题是:有没有一种方法可以像使用生成器一样生成行,但第一行已经准备好,可以说“立即”,延迟几乎为零?


编辑:基于@Lukas KoeSTLer 和@hpaulj 的评论,我尝试了 memmap,但结果出人意料地不好,因为 memmap 在内存上崩溃比简单地加载完整数组更快。

Windows 10

我在磁盘上保存了 1000 个 numpy 数组 (shape = [500,30,3]) 并尝试使用 np.load 和 np.load 缓存它们并使用 memmap 读取

import numpy as np
import os

mats = os.listdir('matrixes')
cache = []
for i in range(10):
for n in mats:
cache.append(np.load('matrixes\\{}'.format(n),mmap_mode='r')) # Load with memmap
#cache.append(np.load('matrixes\\{}'.format(n))) #load without memmap

print('{} objects stored in cache '.format((i+1)*1000))

在运行两种变体(使用和不使用 memmap)之后,出现了这两个错误

存储 4000 个 memmaps 对象后的 Memmap:

...
File "C:\Python27\lib\site-packages\numpy\core\memmap.py", line 264, in __new__
mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
WindowsError: [Error 8] Not enough memory resources are available to process this command

缓存 5000 个 np.arrays 后没有 memmap 的简单 np.load

....
File "C:\Python27\lib\site-packages\numpy\lib\format.py", line 661, in read_array
array = numpy.fromfile(fp, dtype=dtype, count=count)
MemoryError

树莓派零

正如@Alex Yu 所指出的,我在 Windows 10 上进行测试,切换到 raspberry pi Zero,

我得到了超过 1000 个 numpy 数组(花了很长时间)然后我得到了

1000 objects stored in cache
Killed

使用 Memmaps,我很快就超过了 1000 个 memmaps,但我遇到了不同的错误

File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 416, in load
return format.open_memmap(file, mode=mmap_mode)
File "/usr/lib/python2.7/dist-packages/numpy/lib/format.py", line 792, in open_memmap
mode=mode, offset=offset)
File "/usr/lib/python2.7/dist-packages/numpy/core/memmap.py", line 264, in __new__
mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
mmap.error: [Errno 24] Too many open files

如果我没记错的话,这个错误发生在打开很多文件但没有关闭它们的时候。

最佳答案

Thanks to @Lukas Koestler and @hpaulj for directing me into using memmap

and Thanks to @Alex Yu for making the solution reality


我自己的问题的解决方案

使用

np.load(path,mmap_mode='r')

有效,但受打开文件的限制。在 Windows 和 Linux 上抛出不同的错误:

获胜

WindowsError: [Error 8] Not enough memory resources are available to process this command

mmap.error: [Errno 24] Too many open files

这已通过@Alex Yu 提供的链接解决extend limit of opened files .

摘录:

打开

/etc/security/limits.conf

将以下内容粘贴到末尾:

*         hard    nofile      500000
* soft nofile 500000
root hard nofile 500000
root soft nofile 500000

摘录结束

仍然有限制,但它增加了列表中最多 8000 个对象的数量

...
8000 objects stored in cache

直到

Traceback (most recent call last):
...
mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
mmap.error: [Errno 12] Cannot allocate memory

For me this is quite enough


对我的问题的不同态度的概述

测试形状为[500,30,3]的数组

1) 简单加载:无缓存

array = np.load(path)
[process rows]

Slowest but most memory efficient

cache_limit = 0 (Arrays in dictionary)

2) 硬缓存——将数组加载到字典中

cache_raw = {i: np.load(i) for i in os.listdir('array_folder')}
...
temporary_array = cache_raw[some_array]
[process rows with temporary_array]

Ultra fast but very memory inefficient

cache_limit ~ 1000, (RPI zero) (Arrays in dictionary)

3) 内存映射缓存

cache_memmap = {i: np.load(i,mmap_mode='r') for i in os.listdir('array_folder')}
...
memmap_array = cache_memmap[some_array]
[process rows with memmap_array]

reasonable speed, memory effiecient

cache_limit ~ 8000 (RPI zero) (Arrays in dictionary)


结果

加载第一行所有态度的20次随机访问的计时结果:

Memmap
0.00122714042664
0.00237703323364
0.00152182579041
0.000735998153687
0.000724077224731
0.000736951828003
0.000741004943848
0.000698089599609
0.000723123550415
0.000734090805054
0.000775814056396
0.00343084335327
0.000797033309937
0.000717878341675
0.000727891921997
0.000733852386475
0.000690937042236
0.00178194046021
0.000714063644409
0.000691175460815
Hard cache
0.000302076339722
0.000305891036987
0.000910043716431
0.000320911407471
0.000298976898193
0.000309944152832
0.000294923782349
0.000304937362671
0.000298023223877
0.00031590461731
0.000324010848999
0.000273942947388
0.000274181365967
0.000286817550659
0.000277042388916
0.000297784805298
0.000288009643555
0.000318050384521
0.00031304359436
0.000298023223877
Without cache
0.0350978374481
0.0103611946106
0.0172200202942
0.0349309444427
0.0177171230316
0.00722813606262
0.0286860466003
0.0435371398926
0.0261130332947
0.0302798748016
0.0361919403076
0.0286440849304
0.0175659656525
0.035896062851
0.0307757854462
0.0364079475403
0.0258250236511
0.00768494606018
0.025671005249
0.0261180400848

编辑:额外计算:

100 次唯一访问的平均时间。每种态度 5 次

Memmap
0.000535547733307 # very good speed
0.000488042831421
0.000483453273773
0.000485241413116
0.00049720287323
Hard cache
0.000133073329926 # 4x faster than memmap
0.000132908821106
0.000131068229675
0.000130603313446
0.000126478672028
Without cache
0.0996991252899 # very slow
0.0946901941299
0.0264434242249 # Interesting to note here, something I suspected
0.0239776492119 # np.load has cache in itself
0.0208633708954 # If you load particular numpy array more times in the program,
#it will load faster. Kind of integrated cache
# From my own experience, it is very unreliable and cannot be counted with.

关于python - numpy array - 从磁盘逐行加载 - 内存效率高但速度快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54727321/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com