2010-04-19 8 views
5

Ho un set di punti dati, ciascuno descritto da un dizionario. L'elaborazione di ciascun punto di dati è indipendente e invio ciascuno come un lavoro separato a un cluster. Ogni punto di dati ha un nome univoco e il mio wrapper di invio di cluster chiama semplicemente uno script che prende il nome di un punto di dati e un file che descrive tutti i punti di dati. Lo script quindi accede al punto dati dal file ed esegue il calcolo.Serializzazione JSON veloce (e confronto con Pickle) per il cluster computing in Python?

Poiché ogni lavoro deve caricare l'insieme di tutti i punti solo per recuperare il punto da eseguire, ho voluto ottimizzare questo passaggio serializzando il file che descrive l'insieme di punti in un formato facilmente recuperabile.

Ho provato ad utilizzare JSONpickle, utilizzando il seguente metodo, per serializzare un dizionario che descrive tutti i punti dati al file:

def json_serialize(obj, filename, use_jsonpickle=True): 
    f = open(filename, 'w') 
    if use_jsonpickle: 
    import jsonpickle 
    json_obj = jsonpickle.encode(obj) 
    f.write(json_obj) 
    else: 
    simplejson.dump(obj, f, indent=1) 
    f.close() 

Il dizionario contiene oggetti molto semplici (liste, stringhe, galleggianti, ecc) e ha un totale di 54.000 chiavi. Il file json ha una dimensione di ~ 20 Megabyte.

Ci vogliono circa 20 secondi per caricare questo file in memoria, il che mi sembra molto lento. Sono passato a usare pickle con lo stesso oggetto esatto e ho scoperto che genera un file di circa 7,8 megabyte e può essere caricato in ~ 1-2 secondi. Questo è un miglioramento significativo, ma sembra che il caricamento di un oggetto di piccole dimensioni (meno di 100.000 voci) sia più veloce. A parte questo, pickle non è leggibile dall'uomo, il che è stato il grande vantaggio di JSON per me.

C'è un modo per utilizzare JSON per ottenere aumenti di velocità simili o migliori? Se no, hai altre idee su come strutturare questo?

(È la soluzione giusta per "tagliare" semplicemente il file che descrive ogni evento in un file separato e passarlo allo script che esegue un punto dati in un lavoro di cluster? Sembra che ciò potrebbe portare a una proliferazione di File).

grazie.

risposta

7

marshal è più veloce, ma pickle di per sé non è - forse vuoi dire cPickle (che è abbastanza veloce, specialmente con un protocollo -1.).Quindi, a parte i problemi di leggibilità, ecco qualche codice per mostrare diverse possibilità:

import pickle 
import cPickle 
import marshal 
import json 

def maked(N=5400): 
    d = {} 
    for x in range(N): 
    k = 'key%d' % x 
    v = [x] * 5 
    d[k] = v 
    return d 
d = maked() 

def marsh(): 
    return marshal.dumps(d) 

def pick(): 
    return pickle.dumps(d) 

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

def cpick(): 
    return cPickle.dumps(d) 

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

def jso(): 
    return json.dumps(d) 

def rep(): 
    return repr(d) 

e qui sono i loro costi sul mio portatile:

$ py26 -mtimeit -s'import pik' 'pik.marsh()' 
1000 loops, best of 3: 1.56 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.pick()' 
10 loops, best of 3: 173 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.pick1()' 
10 loops, best of 3: 241 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.cpick()' 
10 loops, best of 3: 21.8 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.cpick1()' 
100 loops, best of 3: 10 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.jso()' 
10 loops, best of 3: 138 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.rep()' 
100 loops, best of 3: 13.1 msec per loop 

modo, si può avere la leggibilità e dieci volte le velocità di json.dumps con repr (si sacrifica la facilità di analisi da Javascript e altre lingue); puoi avere la massima velocità assoluta con marshal, quasi 90 volte più veloce di json; cPickle offre molto più generalità (in termini di cosa è possibile serializzare) rispetto a json o marshal, ma se non si utilizzerà mai tale generalità, si potrebbe anche andare per marshal (o repr se la leggibilità umana supera la velocità).

Per quanto riguarda la tua idea di "affettare", al posto di una moltitudine di file, potresti prendere in considerazione un database (una moltitudine di record) - potresti anche andare via senza serializzazione effettiva se stai utilizzando i dati che ha qualche "schema" riconoscibile ad esso.

+0

Grazie mille per la tua risposta informativa, che è stata molto utile. Quali basi di dati consiglieresti in Python? Preferisco di gran lunga cose che non richiedono server di database stand-alone - o ancora meglio che sono integrati in Python, forse come sqlite - su quelli che lo fanno. Qualche idea su questo? Un approccio al database in Python potrebbe rivaleggiare con i tempi di pickle per il caso di test di un dizionario per ~ 50.000 chiavi in ​​cui devi separare una particolare voce da esso? Se passo a un DB, scriverò codice personalizzato per serializzarlo in CSV in modo che i miei file possano essere condivisi e letti da altri utenti umani. – user248237dfsf

+0

Se si utilizza un DB incorporato, sqlite è il migliore, ma come qualsiasi altro DB incorporato non vi offre alcuna elaborazione parallela, ma in questo caso è il punto di forza delle prestazioni del metodo DB. Quanto è difficile eseguire un processo PostgreSQL, dopo tutto? E ora puoi ottenere una perfetta parallelizzazione dell'accesso ai dati e un notevole incremento delle prestazioni. (Scrivere CSV o altri moduli su un DB SQL e riportare il contenuto del DB a qualsiasi forma di tuo gradimento, è un lavoro facile con semplici script ausiliari, ovviamente - che è indipendente dal motore DB che scegli). –

1

Penso che ci si trovi di fronte a un compromesso: la leggibilità umana ha un costo di prestazioni e file di grandi dimensioni. Quindi, tra tutti i metodi di serializzazione disponibili in Python, JSON non è solo il più leggibile, ma anche il più lento.

Se dovessi perseguire le prestazioni (e la compattezza del file), andrei per marshall. È possibile effettuare il marshalling dell'intero set con dump() e load() oppure, basandosi sull'idea di affettare le cose, eseguire il marshalling di parti separate del set di dati in file separati. In questo modo apri la porta per la parallelizzazione dell'elaborazione dei dati, se ti senti così incline.

Naturalmente, ci sono tutti i tipi di restrizioni e avvisi nella documentazione, quindi se si decide di andare sul sicuro, andare per pickle.

+0

JSON è più lento di XML? Non sembra giusto ... –