Python 压缩文件上的有效numpy.fromfile?

Python 压缩文件上的有效numpy.fromfile?,python,numpy,zip,fromfile,Python,Numpy,Zip,Fromfile,我有一些大文件(甚至是10GB左右的压缩文件),其中包含一个ASCII头,然后原则上每个都是3MB左右的numpy.recarray,我们称它们为“事件”。我的第一个方法是这样的: f = gzip.GzipFile(filename) f.read(10000) # fixed length ascii header event_dtype = np.dtype([ ('Id', '>u4'), # simplified ('

我有一些大文件(甚至是10GB左右的压缩文件),其中包含一个ASCII头,然后原则上每个都是3MB左右的numpy.recarray,我们称它们为“事件”。我的第一个方法是这样的:

f = gzip.GzipFile(filename)
f.read(10000) # fixed length ascii header
event_dtype = np.dtype([
        ('Id', '>u4'),                # simplified
        ('UnixTimeUTC', '>u4', 2), 
        ('Data', '>i2', (1600,1024) ) 
        ])
event = np.fromfile( f, dtype = event_dtype, count=1 )
s = f.read( event_dtype.itemsize )
event = np.fromstring(s, dtype=event_dtype, count=1)
但是,这是不可能的,因为np.fromfile需要一个真正的FILE对象,因为它确实进行低级调用(找到一个非常旧的票证)

据我所知,我必须这样做:

f = gzip.GzipFile(filename)
f.read(10000) # fixed length ascii header
event_dtype = np.dtype([
        ('Id', '>u4'),                # simplified
        ('UnixTimeUTC', '>u4', 2), 
        ('Data', '>i2', (1600,1024) ) 
        ])
event = np.fromfile( f, dtype = event_dtype, count=1 )
s = f.read( event_dtype.itemsize )
event = np.fromstring(s, dtype=event_dtype, count=1)
是的,它是有效的!但这不是非常低效吗?不是为每个事件分配了mem,并收集了垃圾吗? 在我的笔记本电脑上,我达到了大约16个事件/秒,即大约50MB/秒

我想知道是否有人知道一种聪明的方法,分配一次mem,然后让numpy直接读取到该mem中


顺便说一句,我是物理学家,所以。。。在这个行业里,我们还是一个新手。

@Bakuriu可能是正确的,这可能是一个微观优化。您的瓶颈几乎肯定是IO,然后是解压缩。分配两次内存可能并不重要

但是,如果希望避免额外的内存分配,可以使用
numpy.frombuffer
将字符串视为numpy数组

这避免了重复内存(字符串和数组使用相同的内存缓冲区),但默认情况下,数组将是只读的。如果需要,您可以将其更改为允许写入

在您的情况下,只需将
fromstring
替换为
fromsbuffer

f = gzip.GzipFile(filename)
f.read(10000) # fixed length ascii header
event_dtype = np.dtype([
        ('Id', '>u4'),                # simplified
        ('UnixTimeUTC', '>u4', 2), 
        ('Data', '>i2', (1600,1024) ) 
        ])
s = f.read( event_dtype.itemsize )
event = np.frombuffer(s, dtype=event_dtype, count=1)
为了证明使用这种方法不会复制内存:

import numpy as np

x = "hello"
y = np.frombuffer(x, dtype=np.uint8)

# Make "y" writeable...
y.flags.writeable = True

# Prove that we're using the same memory
y[0] = 121
print x # <-- Notice that we're outputting changing y and printing x...
将numpy导入为np
x=“你好”
y=np.frombuffer(x,dtype=np.uint8)
#使“y”可写。。。
y、 flags.writeable=True
#证明我们使用的是相同的内存
y[0]=121

打印x#I/O所花费的时间比分配/取消分配该字符串所花费的时间大数千倍。您应该分析代码以查看瓶颈所在,然后对其进行优化。。。猜测瓶颈在哪里是不好的,如果你不习惯高效地编程,那就更糟了。只要你对只读数组没问题,你就可以使用
numpy.frombuffer
,以避免重复内存,而只是将字符串用作内存缓冲区。@Bakariu感谢你清楚地表达了这一点。我没有分析代码的经验。“听到这个消息很高兴,猜测是不好的。”乔·金顿。谢谢你的明确的例子!我会去的。大的加一个给frombuffer!有一段时间,我试图在一个压缩文件上使用fromfile,这就是关键。