2015-07-27 10 views
6

Tworzenie zestawów danych do szkolenia z Caffe Oboje próbowaliśmy używać HDF5 i LMDB. Jednak tworzenie LMDB jest bardzo wolne, nawet wolniejsze niż HDF5. Próbuję napisać ~ 20 000 obrazów.Zapisywanie danych do LMDB z Pythonem bardzo powolne

Czy robię coś strasznego? Czy jest coś, czego nie jestem świadomy?

To jest mój kod do tworzenia 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() 

Jak widać tworzę transakcji na każde 1000 zdjęć, bo myślałem, tworząc transakcji dla każdego obrazu spowodowałoby obciążenie, ale wydaje się, to nie wpływa zbytnio na wydajność.

+0

dlaczego nie używając [ 'convert_imageset'] (http://stackoverflow.com/a/31431716/1714410) narzędzie? – Shai

+0

@Shai: Właściwie nie wiedziałem o tym, ale nie mam też moich zdjęć jako plików. Ale dlaczego miałoby być szybciej? Czy implementacja Pythona jest tak powolna? – Simikolon

+0

Pracuję z 'convert_imageset' do woek na ilsvrc12 (imagenet) konwertując zestawy danych ~ 1M obrazów, to zajmuje trochę czasu, ale działa. – Shai

Odpowiedz

3

Spróbuj tego:

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() 

kod

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

zajmuje dużo czasu.

6

Z mojego doświadczenia wynika, że ​​miałem 50-100 ms zapisuje do LMDB z Python zapisując dane Caffe na ext4 na dysku twardym w systemie Ubuntu. Dlatego używam funkcji tmpfs (RAM disk funkcjonalności wbudowanej w Linuksa) i wykonuję te operacje w około 0.07 ms. Możesz tworzyć mniejsze bazy danych na ramdysku i kopiować je na dysk twardy, a następnie ćwiczyć je wszystkie. Robię około 20-40 GB, ponieważ mam 64 GB pamięci RAM.

Kilka kawałków kodu, które pomogą ci dynamicznie tworzyć, wypełniać i przenosić pliki LMDB do pamięci masowej. Możesz go edytować, aby pasował do Twojego przypadku. Powinno to zaoszczędzić trochę czasu, aby zorientować się, jak LMDB i operacje na plikach działają w Pythonie.

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

Czy możesz podać nieco więcej kontekstu czym jest 'tempfs'? –

+0

Czy możesz podać kod opisujący Twoje rozwiązanie/przepływ pracy? – Shai

+2

To doskonała propozycja! @SteveHeim Zobacz [ten post] (http://askubuntu.com/questions/152868/how-do-i-make-a-ram-disk), aby uzyskać szczegółowe informacje na temat tworzenia dysku RAM w systemie Ubuntu. Zamiast zapisywać dane na dysku twardym, które mogą być bardzo powolne w przypadku dużej liczby zapisów, można zamontować katalog w lokalizacji RAM.Chociaż interfejs jest taki sam, jak każdy inny katalog, dostęp do odczytu i zapisu w zamontowanym katalogu będzie szybszy o rząd wielkości. Po zakończeniu korzystania z bazy danych można przenieść ją do innego katalogu na twardym dysku w celu długoterminowego przechowywania. – Jake

0

pisze LMDB są bardzo wrażliwe na zamówienie - Jeśli można sortować dane przed prędkość wstawiania poprawi znacząco