Me está llevando hasta una hora para leer un 1 gigabyte NetworkX estructura de datos del gráfico utilizando cPickle (su 1 GB cuando se almacena en el disco como un archivo binario archivo pickle).

Nota que rápidamente el archivo se carga en la memoria. En otras palabras, si ejecuto:

import cPickle as pickle

f = open("bigNetworkXGraph.pickle","rb")
binary_data = f.read() # This part doesn't take long
graph = pickle.loads(binary_data) # This takes ages

¿Cómo puedo velocidad de esta última operación hasta?

Nota que he tratado de decapado de los datos tanto en el uso de ambos protocolos binarios (1 y 2), y no parece hacer mucha diferencia el protocolo que yo uso. También tenga en cuenta que aunque yo estoy usando el de «cargas» (que significa «la carga de la cadena») la función anterior, es la carga de datos binarios, no ascii de datos.

He 128gb de RAM en el sistema que estoy usando, así que estoy esperando que alguien me va a decir cómo aumentar algunos de búfer de lectura enterrado en el pepinillo aplicación.

  • ¿De verdad quieres decir 128GB de ram? O 128MB?
  • Me refiero GB de ram, no MB.
InformationsquelleAutor conradlee | 2010-05-04

8 Comentarios

  1. 6

    Probablemente usted está obligado por objeto de Python/creación de la asignación de gastos generales, no la unpickling sí mismo.
    Si es así, poco se puede hacer para acelerar este proceso, excepto la creación de todos los objetos. ¿Necesita toda la estructura a la vez? Si no, usted podría utilizar perezoso de la población de la estructura de los datos (por ejemplo: para representar las partes de la estructura por escabeche cadenas, a continuación, unpickle ellos sólo cuando se accede a ellos).

    • Bien, puedo pensar en algunas maneras de romper la seguridad de estos datos, en cierta medida, (poniendo atributos de nodo en diferentes archivos), pero los bordes del objeto gráfico solo tomar un montón de memoria—y si tengo que almacenar estos en diferentes archivos, y volver a llenar mi gráfico cada vez que lo use, entonces ¿cuál es el punto de serialización? Yo podría almacenar mis datos de gráfico en un borde de la lista.
    • Yo de hecho no creo que la serialización es la mejor solución para su problema. Pickle nunca fue destinado a ser escalable para grandes estructuras de datos. Esto es más el reino de la base de datos como los formatos que soporta acceso aleatorio y de carga en la demanda.
  2. 8

    He tenido un gran éxito en la lectura de un ~750 MB igraph estructura de datos (binario archivo pickle) utilizando cPickle sí mismo. Esto se consigue simplemente el ajuste de la salmuera de carga llame como se mencionó aquí

    Ejemplo fragmento de código en su caso sería algo como:

    import cPickle as pickle
    import gc
    
    f = open("bigNetworkXGraph.pickle", "rb")
    
    # disable garbage collector
    gc.disable()
    
    graph = pickle.load(f)
    
    # enable garbage collector again
    gc.enable()
    f.close()

    Esta definitivamente no es la forma adecuada de hacerlo, sin embargo, se reduce el tiempo necesario drásticamente.

    (Para mí, se redujo de 843.04 s a 41.28 s, alrededor de 20%)

    • por qué usted necesita para permitir que el gc de nuevo? Y sería pickle de Python3 con el protocolo=4 ser más eficientes?
    • no es una buena práctica para mantener el gc está activada por defecto? También, no he probado protocolo=4 de Python3 sin embargo w.r.t el escenario anterior.
    • ¿por casualidad comparar a joblib? Hice esto con un joblib carga, y era al mismo tiempo con y sin cambio de la recolección de basura.
  3. 4

    ¿Por qué no intentar el cálculo de referencias sus datos y su almacenamiento en la memoria RAM con memcached (por ejemplo). Sí, tiene algunas limitaciones, pero como este de los puntos de cálculo de referencias es el camino más rápido (de 20 a 30 veces) de decapado.

    Por supuesto, usted también debe pasar todo el tiempo la optimización de su estructura de datos con el fin de minimizar la cantidad y complejidad de los datos que desea almacenar.

  4. 1

    Esto es ridículo.

    Tengo una enorme ~150MB diccionario (collections.Counter en realidad) que yo estaba en la lectura y la escritura mediante cPickle en formato binario.

    Escrito que tomó cerca de 3 min.

    He dejado de leer a los 16 minutos, con mi RAM completamente ahogados arriba.

    Ahora estoy usando el mariscal, y que se necesita:
    escribir: ~3s

    leer: ~5s

    Yo hago de todo un poco, y me encontré con este artículo.

    Supongo que nunca he mirado en la salmuera de origen, sino que se basa toda una VM para reconstruir el diccionario?

    Debe haber una nota sobre el rendimiento en los objetos muy grandes en la documentación en mi humilde opinión.

  5. 1

    También estoy tratando de acelerar la carga/almacenamiento de networkx gráficos. Estoy usando el adjacency_graph método para convertir el gráfico a algo serialisable, véase, por ejemplo, este código:

    from networkx.generators import fast_gnp_random_graph
    from networkx.readwrite import json_graph
    
    G = fast_gnp_random_graph(4000, 0.7)
    
    with open('/tmp/graph.pickle', 'wb+') as f:
      data = json_graph.adjacency_data(G)
      pickle.dump(data, f)
    
    with open('/tmp/graph.pickle', 'rb') as f:
      d = pickle.load(f)
      H = json_graph.adjacency_graph(d)

    Sin embargo, este adjacency_graph método de conversión es bastante lento, por lo que el tiempo ganado en el decapado es probablemente perdió en la conversión.

    Así que esto en realidad no acelerar las cosas, decepción. Ejecutando este código concede a los intervalos siguientes:

    N=1000
    
        0.666s ~ generating
        0.790s ~ converting
        0.237s ~ storing
        0.295s ~ loading
        1.152s ~ converting
    
    N=2000
    
        2.761s ~ generating
        3.282s ~ converting
        1.068s ~ storing
        1.105s ~ loading
        4.941s ~ converting
    
    N=3000
    
        6.377s ~ generating
        7.644s ~ converting
        2.464s ~ storing
        2.393s ~ loading
        12.219s ~ converting
    
    N=4000
    
        12.458s ~ generating
        19.025s ~ converting
        8.825s ~ storing
        8.921s ~ loading
        27.601s ~ converting

    Este crecimiento exponencial se debe probablemente a la gráfica exponencialmente más bordes. Aquí es una prueba esencial, en caso de que usted desea para tratar de usted mismo

    https://gist.github.com/wires/5918834712a64297d7d1

  6. 0

    Tal vez la mejor cosa que puedes hacer es dividir los grandes datos en el objeto más pequeño, más pequeño, digamos, de 50 mb, por lo que pueden ser almacenados en la memoria ram, y se recombinan.

    Afaik no hay forma de división automática de datos a través de pepinillo módulo, de modo que usted tiene que hacer por sí mismo.

    De todos modos, de otra manera (que es bastante más difícil) es el uso de algunos Base De Datos NoSQL como MongoDB para almacenar sus datos…

    • él tiene 128 gb de memoria RAM, ¿por qué iba a hacer todo el fraccionamiento?
    • Supongo que él quiere escribir 128 MB de ram…
    • No, me refiero a 128 GB – es una gran máquina. Yo también tengo 24 núcleos de utilizar, de manera paralela solución sería bueno, aunque supongo que el GIL no se realmente que esto sea posible.
    • Wooops! GRAN equipo 🙂 lo Siento por mal entendido!
  7. 0

    En general, he encontrado que si es posible, al guardar objetos de gran tamaño en el disco en python, es mucho más eficaz el uso de numpy ndarrays o scipy.matrices dispersas.

    Por lo tanto para grandes gráficos como la del ejemplo, podría convertir la gráfica a un scipy matriz dispersa (networkx tiene una función que hace esto, y no es difícil escribir uno) y, a continuación, guardar la matriz dispersa en formato binario.

  8. -4

    ¿por qué no utilizar pickle.load?

    f = open('fname', 'rb')
    graph = pickle.load(f)
    • Que probablemente no va a ayudar; la lectura una parte lo suficientemente rápido, y no hay suficiente memoria, por lo que unpickling directamente desde la corriente no ganan mucho.
    • Esa es la primera cosa que hice. Me muestran el más complicado de la carga de un archivo pickle para ilustrar que la lectura de los datos binarios en la memoria ram no parece ser el cuello de botella.

Dejar respuesta

Please enter your comment!
Please enter your name here