open dumps cpickle python serialization caching

dumps - pickle python stack



Serialización de la lista de Python-método más rápido (6)

Necesito cargar (deserializar) una lista precomputada de enteros de un archivo en un script de Python (en una lista de Python). La lista es grande (hasta millones de elementos) y puedo elegir el formato en el que la almaceno, siempre que la carga sea más rápida.

¿Cuál es el método más rápido y por qué?

  1. Usar la import en un archivo .py que solo contiene la lista asignada a una variable
  2. Usando la load cPickle
  3. Algún otro método (tal vez numpy ?)

Además, ¿cómo puede uno comparar tales cosas de manera confiable?

Adición: medir esto de manera confiable es difícil, porque la import se almacena en caché por lo que no se puede ejecutar varias veces en una prueba. La carga con pickle también se vuelve más rápida después de la primera vez probablemente porque el SO precaching de la página. Cargar 1 millón de números con cPickle lleva 1.1 segundos la primera vez que se ejecuta y 0.2 segundos en las ejecuciones posteriores de la secuencia de comandos.

Intuitivamente, creo que cPickle debería ser más rápido, pero apreciaría los números (creo que es un gran desafío medir).

Y sí, es importante para mí que esto funcione rápidamente.

Gracias


Para ayudarlo con el tiempo, la Biblioteca de Python proporciona el módulo de tiempo:

Este módulo proporciona una manera simple de cronometrar pequeños bits de código Python. Tiene tanto línea de comando como interfaces invocables. Evita una serie de trampas comunes para medir los tiempos de ejecución.

Un ejemplo (del manual) que compara el costo de usar hasattr() vs. try/except para probar los atributos de objetos perdidos y presentes:

% timeit.py ''try:'' '' str.__nonzero__'' ''except AttributeError:'' '' pass'' 100000 loops, best of 3: 15.7 usec per loop % timeit.py ''if hasattr(str, "__nonzero__"): pass'' 100000 loops, best of 3: 4.26 usec per loop % timeit.py ''try:'' '' int.__nonzero__'' ''except AttributeError:'' '' pass'' 1000000 loops, best of 3: 1.43 usec per loop % timeit.py ''if hasattr(int, "__nonzero__"): pass'' 100000 loops, best of 3: 2.23 usec per loop


Para la evaluación comparativa, vea el módulo de tiempo en la biblioteca estándar de Python. Para ver cuál es la manera más rápida, implemente todas las formas en que puede pensar y mida con timeit.

Pensamiento aleatorio: dependiendo de lo que esté haciendo exactamente, puede encontrar que es más rápido almacenar "conjuntos de enteros" en el estilo utilizado en los archivos .newsrc :

1, 3-1024, 11000-1200000

Si necesita verificar si algo está en ese conjunto, entonces la carga y el emparejamiento con dicha representación deberían estar entre las formas más rápidas. Esto supone que tus conjuntos de enteros son razonablemente densos, con largas secuencias consecutivas de valores adyacentes.


cPickle será el más rápido, ya que se guarda en binario y no se debe analizar ningún código python real.

Otras ventajas son que es más seguro (ya que no ejecuta comandos) y no tiene problemas para configurar $PYTHONPATH correctamente.


¿Necesitas siempre cargar todo el archivo? De lo contrario, upack_from () podría ser la mejor solución. Supongamos que tiene 1000000 enteros, pero desea cargar solo los de 50000 a 50099, haría:

import struct intSize = struct.calcsize(''i'') #this value would be constant for a given arch intFile = open(''/your/file.of.integers'') intTuple5K100 = struct.unpack_from(''i''*100,intFile,50000*intSize)


Supongo que cPickle será más rápido si realmente necesitas la cosa en una lista.

Si puede usar una matriz , que es un tipo de secuencia integrada, calculé esto en un cuarto de segundo por 1 millón de enteros:

from array import array from datetime import datetime def WriteInts(theArray,filename): f = file(filename,"wb") theArray.tofile(f) f.close() def ReadInts(filename): d = datetime.utcnow() theArray = array(''i'') f = file(filename,"rb") try: theArray.fromfile(f,1000000000) except EOFError: pass print "Read %d ints in %s" % (len(theArray),datetime.utcnow() - d) return theArray if __name__ == "__main__": a = array(''i'') a.extend(range(0,1000000)) filename = "a_million_ints.dat" WriteInts(a,filename) r = ReadInts(filename) print "The 5th element is %d" % (r[4])


"¿cómo puede uno comparar tales cosas de manera confiable?"

No entiendo la pregunta

Usted escribe una serie de pequeñas funciones para crear y guardar su lista en varias formas.

Usted escribe un montón de pequeñas funciones para cargar sus listas en sus diversas formas.

Usted escribe una pequeña función de temporizador para obtener la hora de inicio, ejecuta el procedimiento de carga unas docenas de veces (para obtener un promedio sólido que sea lo suficientemente largo como para que el ruido de programación del sistema operativo no domine sus mediciones).

Resume sus datos en un pequeño informe.

¿Qué no es confiable acerca de esto?

Aquí hay algunas preguntas no relacionadas que muestran cómo medir y comparar el rendimiento.

Convierte la lista de entradas a un número?

Concatenación de cadenas vs. sustitución de cadenas en Python