2015-07-27 10 views
6

Creazione di serie di dati per l'allenamento con Caffe Entrambi ho provato a utilizzare HDF5 e LMDB. Tuttavia, la creazione di un LMDB è molto lenta anche più lentamente di HDF5. Sto cercando di scrivere ~ 20.000 immagini.Scrittura dei dati su LMDB con Python molto lento

Sto facendo qualcosa di terribilmente sbagliato? C'è qualcosa di cui non sono a conoscenza?

Questo è il mio codice per la creazione LMDB:

DB_KEY_FORMAT = "{:0>10d}" 
db = lmdb.open(path, map_size=int(1e12)) 
    curr_idx = 0 
    commit_size = 1000 
    for curr_commit_idx in range(0, num_data, commit_size): 
     with in_db_data.begin(write=True) as in_txn: 
      for i in range(curr_commit_idx, min(curr_commit_idx + commit_size, num_data)): 
       d, l = data[i], labels[i] 
       im_dat = caffe.io.array_to_datum(d.astype(float), label=int(l)) 
       key = DB_KEY_FORMAT.format(curr_idx) 
       in_txn.put(key, im_dat.SerializeToString()) 
       curr_idx += 1 
    db.close() 

Come potete vedere sto creando una transazione per ogni 1.000 immagini, perché ho pensato di creare una transazione per ogni immagine creerebbe un sovraccarico, ma sembra questo non influenza troppo le prestazioni.

+0

perché non stai usando il [ 'convert_imageset'] (http://stackoverflow.com/a/31431716/1714410) strumento? – Shai

+0

@Shai: In realtà non ne ero a conoscenza, ma non ho nemmeno le mie immagini come file. Tuttavia, perché dovrebbe essere più veloce? L'implementazione di Python è così lenta? – Simikolon

+0

Sto lavorando con 'convert_imageset' su woek su ilsvrc12 (imagenet) convertendo i dataset di ~ 1M immagini, ci vuole un po 'ma funziona. – Shai

risposta

3

Prova questo:

DB_KEY_FORMAT = "{:0>10d}" 
db = lmdb.open(path, map_size=int(1e12)) 
    curr_idx = 0 
    commit_size = 1000 
    with in_db_data.begin(write=True) as in_txn: 
     for curr_commit_idx in range(0, num_data, commit_size): 
      for i in range(curr_commit_idx, min(curr_commit_idx + commit_size, num_data)): 
       d, l = data[i], labels[i] 
       im_dat = caffe.io.array_to_datum(d.astype(float), label=int(l)) 
       key = DB_KEY_FORMAT.format(curr_idx) 
       in_txn.put(key, im_dat.SerializeToString()) 
       curr_idx += 1 
    db.close() 

il codice

with in_db_data.begin(write=True) as in_txn: 

richiede molto tempo.

6

Nella mia esperienza, ho avuto 50-100 ms scrive in LMDB da Python scrivendo i dati Caffe su disco rigido ext4 su Ubuntu. Ecco perché uso tmpfs (disco RAM funzionalità incorporate in Linux) e ottenere queste scritture eseguite intorno a 0,07 ms. Puoi creare database più piccoli sul tuo ramdisk e copiarli su un disco rigido per poi allenarti su tutti. Sto facendo circa 20-40GB in quanto ho 64 GB di RAM.

Alcune parti di codice per aiutare i ragazzi a creare, riempire e spostare dinamicamente gli LMDB in modo dinamico. Sentiti libero di modificarlo per adattarlo al tuo caso. Dovresti risparmiare tempo per capire come funziona LMDB e la manipolazione dei file in Python.

import shutil 
import lmdb 
import random 


def move_db(): 
    global image_db 
    image_db.close(); 
    rnd = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(5)) 
    shutil.move(fold + 'ram/train_images', '/storage/lmdb/'+rnd) 
    open_db() 


def open_db(): 
    global image_db 
    image_db = lmdb.open(os.path.join(fold, 'ram/train_images'), 
      map_async=True, 
      max_dbs=0) 

def write_to_lmdb(db, key, value): 
    """ 
    Write (key,value) to db 
    """ 
    success = False 
    while not success: 
     txn = db.begin(write=True) 
     try: 
      txn.put(key, value) 
      txn.commit() 
      success = True 
     except lmdb.MapFullError: 
      txn.abort() 
      # double the map_size 
      curr_limit = db.info()['map_size'] 
      new_limit = curr_limit*2 
      print '>>> Doubling LMDB map size to %sMB ...' % (new_limit>>20,) 
      db.set_mapsize(new_limit) # double it 

... 

image_datum     = caffe.io.array_to_datum(transformed_image, label) 
write_to_lmdb(image_db, str(itr), image_datum.SerializeToString()) 
+1

Puoi dare un po 'più di contesto cosa sia 'tempfs'? –

+0

È possibile fornire un codice specifico che descriva la soluzione/il flusso di lavoro? – Shai

+2

Questo è un eccellente suggerimento! @SteveHeim Vedi [questo post] (http://askubuntu.com/questions/152868/how-do-i-make-a-ram-disk) per i dettagli sulla creazione di un disco RAM in Ubuntu. Piuttosto che scrivere dati su un disco rigido, che può essere molto lento quando è coinvolto un numero elevato di scritture, è possibile montare una directory in una posizione RAM.Mentre l'interfaccia è uguale a qualsiasi altra directory, l'accesso in lettura e scrittura alla directory montata sarà più veloce di ordini di grandezza. Una volta terminato di utilizzare il database, è possibile spostarlo in un'altra directory su un disco rigido per la memorizzazione a lungo termine. – Jake

0

scrive LMDB sono molto sensibili su ordinazione - Se è possibile ordinare i dati prima che la velocità di inserimento migliorerà in modo significativo