print python sum byte checksum ord

print bytearray python



Python cómo calcular una suma de comprobación simple tan rápido como zlib.adler32 (2)

Deseo calcular una suma de comprobación simple: simplemente agregando los valores de todos los bytes.

La forma más rápida que encontré es:

checksum = sum([ord(c) for c in buf])

Pero para los datos de 13 Mb, tarda 4,4 s: demasiado tiempo (en C, tarda 0,5 s)

Si uso:

checksum = zlib.adler32(buf) & 0xffffffff

lleva 0,8 s, pero el resultado no es el que yo quiero.

Entonces mi pregunta es: ¿hay alguna función, lib o C para incluir en Python 2.6, para calcular una suma de comprobación simple?

Gracias por adelantado, Eric.


Puede usar sum(bytearray(buf)) :

In [1]: buf = b''a''*(13*(1<<20)) In [2]: %timeit sum(ord(c) for c in buf) 1 loops, best of 3: 1.25 s per loop In [3]: %timeit sum(imap(ord, buf)) 1 loops, best of 3: 564 ms per loop In [4]: %timeit b=bytearray(buf); sum(b) 10 loops, best of 3: 101 ms per loop

Aquí hay una extensión C para Python escrita en Cython , sumbytes.pyx file:

from libc.limits cimport ULLONG_MAX, UCHAR_MAX def sumbytes(bytes buf not None): cdef: unsigned long long total = 0 unsigned char c if len(buf) > (ULLONG_MAX // <size_t>UCHAR_MAX): raise NotImplementedError #todo: implement for > 8 PiB available memory for c in buf: total += c return total

sumbytes es ~ 10 veces más rápido que la variante de bytearray :

name time ratio sumbytes_sumbytes 12 msec 1.00 sumbytes_numpy 29.6 msec 2.48 sumbytes_bytearray 122 msec 10.19

Para reproducir las medidas de tiempo, descargue reporttime.py y ejecute:

#!/usr/bin/env python # compile on-the-fly import pyximport; pyximport.install() # pip install cython import numpy as np from reporttime import get_functions_with_prefix, measure from sumbytes import sumbytes # from sumbytes.pyx def sumbytes_sumbytes(input): return sumbytes(input) def sumbytes_bytearray(input): return sum(bytearray(input)) def sumbytes_numpy(input): return np.frombuffer(input, ''uint8'').sum() # @root''s answer def main(): funcs = get_functions_with_prefix(''sumbytes_'') buf = ''''.join(map(unichr, range(256))).encode(''latin1'') * (1 << 16) measure(funcs, args=[buf]) main()


Use numpy.frombuffer(buf, "uint8").sum() , parece ser aproximadamente 70 veces más rápido que su ejemplo:

In [9]: import numpy as np In [10]: buf = b''a''*(13*(1<<20)) In [11]: sum(bytearray(buf)) Out[11]: 1322254336 In [12]: %timeit sum(bytearray(buf)) 1 loops, best of 3: 253 ms per loop In [13]: np.frombuffer(buf, "uint8").sum() Out[13]: 1322254336 In [14]: %timeit np.frombuffer(buf, "uint8").sum() 10 loops, best of 3: 36.7 ms per loop In [15]: %timeit sum([ord(c) for c in buf]) 1 loops, best of 3: 2.65 s per loop