2011-11-16 3 views
6

파이썬에서 이진 데이터 문자열을 숫자 값으로 변환하는 가장 빠른 방법은 무엇입니까?파이썬에서 빠른 이진 데이터 변환

나는 struct.unpack_from()을 사용하고 있지만 성능 제한이 있습니다.

컨텍스트 : 들어오는 스트림은 2 진수와 ASCII 데이터가 혼합되어 있습니다. ASCII 데이터 변환은 ctype을 통해 C에서 수행됩니다. ctypes를 통해 C에서 압축 풀기를 구현하면 압축을 풀 때와 비슷한 성능이 나타납니다. 내 생각 엔 전화 오버 헤드가 너무 많은 요인이었다. 나는 네이티브 C와 같은 강제 변환 방법 (un Pythonic)을 찾기를 희망했다. 대부분이 코드는 C로 이동해야합니다.

스트림은 네트워크 바이트 순서 (빅 엔디안)이며 시스템은 리틀 엔디안입니다. 내가 바이너리 변환의 일반적인 경우보다, 스트림 형식 처리에 대해 덜 걱정

import struct 
network_stream = struct.pack('>I', 0x12345678) 
(converted_int,) = struct.unpack_from('>I', network_stream, 0) 

unpack 심지어 대안이있는 경우 : 예 변환 될 것이다. 예를 들어 socket.ntohl()에는 int가 필요하고 int()은 이진 데이터 문자열을 변환하지 않습니다.

의견을 보내 주셔서 감사합니다. 내 경험을 바탕으로

+0

정확히 풀고있는 것은 무엇입니까? 단순히 숫자 값의 일정한 배열입니까? –

+0

불행히도 싱글 톤의 혼합 된 스트림이며 내용은 헤더로 표시됩니다. 대부분의 변환은 4B 정수 및 부동 소수점에 대한 것입니다. – CNK

+1

테스트 케이스가 여기 좋을 것이라고 – Triptych

답변

2

속도 문제는 아마도 struct.unpack_from()의 구현이 아니라 파이썬이 — 사전 조회, 객체 만들기, 함수 호출 및 다른 작업을 수행해야합니다. 각 시간을 unpack_from을 가져 이러한 사전 조회 중 하나를 제거하지 않고 직접 struct 모듈에서 그것을 얻어서 약간 이제까지 일을 속도를 높일 수 있습니다 : 구문 분석 로직이 많이있을 필요가있는 경우,

$ python -m timeit -s "import struct; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = struct.unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.277 usec per loop 

$ python -m timeit -s "import struct; from struct import unpack_from; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.258 usec per loop 

그러나 그 한 번에 하나의 번호를 풀어야하며, 전체 데이터 배열을 일괄 적으로 풀지 않도록 할 것입니다. 아마도 C와 같은 오버 헤드가 적은 언어로이 내부 루프를 수행해야 할 것입니다.

+0

흥미로운 생각. 사실'from struct import *'를 사용했습니다. 이 예제를 모방하여 약 220M 통화보다 5 % 성능 차이를 발견했습니다. 결코 그걸 기대하지 않았을 것입니다. 감사! – CNK

2

, 당신은 바이너리 변환을위한 다양한 도구의 성능을 발견으로 코드가 C로 이동해야한다는 올바른지 (struct 예를 들면 ctypes)은 대략 비슷한 성능을 가지고 .

Cython은 Python 용 C 확장을 생성하는 가장 쉬운 방법입니다.

또 다른 쉬운 접근법은 CPython을 완전히 포기하여 추적 JIT를 사용하여 고품질, 저수준 코드를 생성 할 수있는 pypy입니다.

좀 더 도전적이지만보다 직접적인 접근법은 일반 C 확장을 작성하는 것입니다. 이것은 재미 없지만 어렵지 않습니다.

+0

호출 오버 헤드가 가장 적은 것으로 추정되는 방법은? C 확장자가 ctypes를 사용하는 것보다 효율적입니까? – CNK

+1

C 확장은 목록이나 반복자의 숫자를 반환 할 때마다 한 번에 많은 변환을 수행 할 수 있기 때문에 항상 승리 할 수 ​​있습니다. * ctypes * 접근 방식은 변환 당 하나의 호출 단위로 세분화되어 있습니다. 또한 * 모든 * 데이터를 원하지 않으므로 C 확장자는 많은 변환/할당/비교/비교/점프/감소 사이클을 저장하여 원치 않는 값을 건너 뛸 수 있습니다. –