2013-04-12 4 views
8

나는 ASCII 헤더를 포함하고 약 3MB 각각의 원칙적으로 numpy.recarrays를 포함하는 큰 (심지어 gzip으로 압축 된 약 10GB) 파일을 가지고 있는데, 우리는 그것을 "이벤트"라고 부른다. 내 첫 번째 방법은 다음과 같이 보았다 : np.fromfile 실제 FILE 객체를 필요로하기 때문에 정말 낮은 수준의 전화를 (꽤 오래된 티켓 https://github.com/numpy/numpy/issues/1103을 발견) 만들기 때문에효율적인 zip 파일의 numpy.fromfile?

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/s와 같은 것에 도달합니다.

누군가가 현명한 방법을 알고 있다면 mem을 한 번 할당 한 다음 해당 numpy를 해당 mem에 직접 읽게합니다.

btw. 나는 물리학 자요. 그럼 ...이 사업에서 여전히 초보자입니다.

+1

I/O에 걸린 시간은 해당 문자열을 할당/할당 해제하는 데 걸리는 시간보다 크고 * 천 배인 것과 같습니다. 병목 현상이 어디 있는지 확인하고 최적화하는 코드를 프로파일 링해야합니다 ... 효율적으로 프로그래밍하는 데 익숙하지 않은 경우 병목 현상이 나쁜 곳을 추측합니다. – Bakuriu

+1

읽기 전용 어레이가 괜찮 으면, numpy.frombuffer를 사용하여 메모리를 복사하지 않고 문자열을 메모리 버퍼로 사용할 수 있습니다. –

+0

@Bakariu는 그 말을 명확하게 표현해 주셔서 감사합니다. 코드 프로파일 링에 대한 경험이 없습니다. 그리고 듣기 좋게, 그 추측은 나쁘다. –

답변

3

@Bakuriu는 아마 이것이 마이크로 최적화 일 가능성이 큽니다. 귀하의 병목 현상은 거의 확실하게 입출력이며, 그 후에 감압됩니다. 아마 메모리를 두 번 할당하는 것은 중요하지 않습니다.

그러나 여분의 메모리 할당을 피하려면 numpy.frombuffer을 사용하여 문자열을 수십 개의 배열로 볼 수 있습니다.

이렇게하면 메모리가 중복되지 않으므로 (문자열과 배열은 동일한 메모리 버퍼를 사용함) 배열은 기본적으로 읽기 전용이됩니다. 필요한 경우 쓰기를 허용하도록 변경할 수 있습니다.

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) 

그냥 그 메모리를 증명하기 위해 중복되지 않는이 방법을 사용하여 : : 대신 yello :

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... 

이 수율을 귀하의 경우에는

, 그것은 frombufferfromstring을 교체하는 것처럼 간단 할 것 hello

이 특별한 경우에 중요한 최적화인지 여부에 관계없이, 알고 있어야하는 유용한 접근 방법입니다.