Tengo una estructura de árbol de widgets por ejemplo, la colección contiene los modelos y el modelo contiene los widgets. Quiero copiar toda la colección, copy.deepcopy es más rápido en comparación a ‘pickle y de pepinillo ing del objeto, sino cPickle como está escrito en C es mucho más rápido, por lo que

  1. ¿Por qué no me(nos) utilizar siempre cPickle en lugar de deepcopy?
  2. Hay ninguna copia de otra alternativa? porque pickle es más lento que deepcopy pero cPickle es más rápido, por lo que puede ser una implementación en C de deepcopy será el ganador

Muestra el código de la prueba:

import copy
import pickle
import cPickle

class A(object): pass

d = {}
for i in range(1000):
    d[i] = A()

def copy1():
    return copy.deepcopy(d)

def copy2():
    return pickle.loads(pickle.dumps(d, -1))

def copy3():
    return cPickle.loads(cPickle.dumps(d, -1))

Tiempos:

>python -m timeit -s "import c" "c.copy1()"
10 loops, best of 3: 46.3 msec per loop

>python -m timeit -s "import c" "c.copy2()"
10 loops, best of 3: 93.3 msec per loop

>python -m timeit -s "import c" "c.copy3()"
100 loops, best of 3: 17.1 msec per loop
  • Esta es una muy útil la observación.
  • hm, ¿no deberías estar comparando pickle con copy.copy?
  • ¿De que depende en absoluto de la estructura de lo que se va a copiar? Como en, hace una diferencia si, por ejemplo, la memoria asignada a los objetos copiados es no contiguas o la subyacente punteros de tener una larga cadena de seguir?
  • pickle hace un deepcopy

5 Comentarios

  1. 31

    Problema es, pepinillo+unpickle puede ser más rápido (en la implementación de C) porque es menos general de deepcopy: muchos objetos pueden ser deepcopied pero no en escabeche. Supongamos por ejemplo que la clase A se cambiaron a…:

    class A(object):
      class B(object): pass
      def __init__(self): self.b = self.B()

    ahora, copy1 todavía funciona muy bien (A la complejidad del sistema se ralentiza downs pero absolutamente no pare); copy2 y copy3 descanso, el fin de la traza de la pila dice…:

      File "./c.py", line 20, in copy3
        return cPickle.loads(cPickle.dumps(d, -1))
    PicklingError: Can't pickle <class 'c.B'>: attribute lookup c.B failed

    I. e., decapado siempre se supone que las clases y funciones de nivel superior de las entidades en sus módulos, y así encurtidos ellos «por su nombre» — deepcopying no hace ninguna de esas hipótesis.

    Así que si usted tiene una situación donde la velocidad de «un poco de profundidad a la copia» es absolutamente crucial, cada milésima de segundo cuenta, Y ustedes quieren tomar ventaja de las limitaciones especiales que usted SABE que se aplican a los objetos que se está duplicando, tales como aquellos que hacen de decapado aplicable, o favoreciendo otras formas todavía de serializations y otros accesos directos, por todos los medios seguir adelante, pero si usted lo que usted DEBE ser consciente de que le está limitando su sistema para vivir por esas limitaciones para siempre, y el documento que la decisión de diseño muy claro y explícito para el beneficio de las futuras mantenedores.

    Para el caso NORMAL, en la que desea generalidad, uso deepcopy!-)

  2. 6

    Usted debe utilizar deepcopy porque hace que el código sea más legible. El uso de un mecanismo de serialización para copiar objetos en la memoria es al menos confusa para otro desarrollador de la lectura de su código. El uso de deepcopy también significa llegar a cosechar los beneficios de las futuras optimizaciones en deepcopy.

    Primera regla de la optimización: no.

    • Segunda regla de optimización: aún no
    • Olvidar las normas antiguas, en sustitución de deepcopy por cpickle, hace que mi proyecto de representación de un 25% más rápido y hace que mi cliente feliz 🙂
    • también creo que no sería confuso si la función de contenedor para copiar objeto se denomina deepcopyObject con un buen comentario
    • si vas a tener problemas de velocidad, por todos los medios. A pesar de que todavía se ve como más de una curita para mí.
    • En lugar de optimización con cPickle, me sugieren la implementación de __deepcopy__ (ver mis respuestas separada).
  3. 2

    Es no siempre el caso de que cPickle es más rápido que deepcopy(). Mientras cPickle probablemente es siempre más rápido que el pepinillo, si es más rápido que deepcopy depende de

    • el tamaño y el nivel de anidamiento de las estructuras a ser copiado,
    • el tipo de objetos que contienen, y
    • el tamaño de la curtido de representación de cadena.

    Si algo puede ser en escabeche, obviamente se puede deepcopied, pero lo contrario no es el caso: con el fin De pepinillo algo, tiene que ser totalmente serializado; este no es el caso de deepcopying. En particular, usted puede implementar __deepcopy__ de manera muy eficiente por la copia de una estructura en la memoria (creo que de los tipos de extensión), sin ser capaz de guardar todo en el disco. (Creo que de la suspensión a RAM vs suspend-to-disk.)

    Un conocido tipo de extensión que cumple las condiciones anteriores puede ser ndarray, y, de hecho, sirve como un buen contraejemplo para su observación: Con d = numpy.arange(100000000), el código da diferentes tiempos de ejecución:

    In [1]: import copy, pickle, cPickle, numpy
    
    In [2]: d = numpy.arange(100000000)
    
    In [3]: %timeit pickle.loads(pickle.dumps(d, -1))
    1 loops, best of 3: 2.95 s per loop
    
    In [4]: %timeit cPickle.loads(cPickle.dumps(d, -1))
    1 loops, best of 3: 2.37 s per loop
    
    In [5]: %timeit copy.deepcopy(d)
    1 loops, best of 3: 459 ms per loop

    Si __deepcopy__ no está implementado, copy y pickle compartir infraestructura común (cf. copy_reg módulo, se discutió en Relación entre la salmuera y deepcopy).

  4. 1

    Incluso más rápido sería para evitar la copia en el primer lugar. Usted menciona que se están haciendo de representación. ¿Por qué necesita para copiar objetos?

    • sí, lo ideal sería que no necesitas copiar, como la vista(de representación) y el modelo de acoplados, pero en mi caso, la representación que hace modificar el modelo por lo tanto tengo que copiar el modelo antes de la representación tan original no conseguir modificado
    • No me refiero a vencer a un caballo muerto, pero solucionar el problema donde la representación se modifica el modelo te hará muy feliz.
    • Estoy de acuerdo, pero sería un asunto costoso para cambiar mucho código, como la discusión aquí no es posible, he añadido una pregunta stackoverflow.com/questions/1414246/…
  5. 0

    Corto y algo tardía:

    • Si usted tiene que cPickle un objeto de todos modos, usted podría utilizar el cPickle método para deepcopy (pero en el documento)

    por ejemplo, Usted podría considerar la posibilidad de:

    def mydeepcopy(obj):
        try:
           return cPickle.loads(cPickle.dumps(obj, -1))
        except PicklingError:
           return deepcopy(obj)
    • ¿por qué mis nuevas líneas de desaparecer, error en stov?
    • pero esa no fue la pregunta, yo ya estaba usando cPickle en forma similar
    • La forma más rápida de lo que yo podía pensar, aparte de escribir su propio python c extensión
    • fija el código de formato

Dejar respuesta

Please enter your comment!
Please enter your name here