Paralel hashing pe gpu în timp real

Parcurgerea paralelă a GPU-ului în timp real

Rezumatul oferă un algoritm eficient de paralelism de date pentru construirea tabelelor hash mari pentru milioane de elemente în timp real. Sunt luați în considerare doi algoritmi paralel: abordarea clasică a hashing-ului și a cache-ului hash, în care elementele sunt împachetate strâns, permițând stocarea elementului într-una din mai multe locații posibile. Se propune și o abordare hibridă care utilizează ambii algoritmi. Acesta a măsurat timpul de construire a tabelelor, timpul de acces și utilizarea memoriei implementărilor propuse și demonstrarea în timp real a seturilor de date mari: pentru 5 milioane de perechi cheie-valoare, tabela hash este construită în 35,7 ms folosind 1,42 ori mai multă memorie , decât datele de intrare în sine și puteți accesa toate elementele acestei tabele de tip hash în 15,3 ms. În schimb, pentru a sorta aceleași date sunt necesare 36,6 ms, iar accesul la toate elementele folosind căutarea binară necesită 79,5 ms.

Hashing (uneori hashing) - convertirea unei matrice de date de lungime arbitrară într-un șir de biți de ieșire cu lungime fixă. Astfel de transformări sunt numite și funcții hash sau funcții fold.

O tabelă hash este o structură de date care implementează interfața unei matrice asociative, adică vă permite să stocați perechi (cheie, valoare) și să efectuați trei operații:

funcționarea adăugării unei noi perechi;

operațiunea de ștergere a unei perechi de o cheie.

O coliziune a unei funcții hash h se numește două blocuri diferite de date de intrare x și y astfel încât h (x) = h (y). Există coliziuni pentru cele mai multe funcții de tip hash, dar pentru funcțiile hash "bune", frecvența generării lor este apropiată de minimul teoretic.

Apariția hardware grafică programabilă a permis GPU-urilor paralele să calculeze și să utilizeze diferite vizualizări de date.

De exemplu, cercetătorii au demonstrat recent o construcție paralelă eficientă pentru structurile ierarhice spațiale de date, cum ar fi arborii k-d (copaci k-dimensionali). În general, o problemă semnificativă pentru cercetare este definirea unor structuri de date paralele adecvate care pot fi create, modificate și accesate. Instrumentele pentru procesarea structurilor de date și algoritmii conexe rămân semnificativ mai mari pe o arhitectură scalară, de exemplu, pe o unitate de procesare centrală (CPU) decât pe o arhitectură paralelă, cum ar fi unitățile de procesare grafică.

Acest articol abordează problema implementării unei structuri de date paralele care oferă acces aleatoriu la milioane de elemente și care poate fi construită într-un timp scurt. O astfel de structură de date are numeroase aplicații în grafica computerizată, axată pe aplicații care necesită stocarea unui set rar de elemente într-o reprezentare compactă. Pe procesorul central, cea mai comună structură de date pentru o astfel de sarcină este o tabelă de tip hash. Cu toate acestea, algoritmii secvențiali convenționali pentru tabelele hash de construire și de asistare nu sunt ușor de tradus într-un mediu GPU paralel din trei motive.

Algoritmii de umplere ai unei tabele tradiționale de tip hash au tendința de a implica operații secvențiale. Formarea unui lanț, de exemplu, necesită adăugarea mai multor elemente la fiecare listă conectată, ceea ce ar necesita serializarea accesului la structura listei de pe GPU.

2) Secvența eșantioanelor.

Secvența în care sunt scanate celulele tabelului hash se numește o secvență de sonde. Numărul de probe necesare pentru căutarea de celule într-un tipic tabele de dispersie succesive, variază în funcție de cerere, de exemplu, pentru lanțul necesită trecerea listelor legate, care variază în lungime. Acest lucru va duce la ineficiențe în GPU, unde nucleele SIMD vor determina toate firele să aștepte cel mai rău caz.

Tabelele hash sunt în mod inerent mici în orice caz de construire sau de acces, astfel încât ierarhiile computaționale au o capacitate mică de a îmbunătăți performanța.

Un avantaj major al tabelului hash în calcule succesive este că acesta este, de fapt, structuri dinamice de date, pentru care îndepărtarea și inserarea forma O (1). Dar de multe ori nu este nevoie de a avea o structură de date dinamice pe GPU: în cazul în care unele sau toate elementele de date din tabelul hash sunt schimbate la fiecare pas, masa este restaurat de la zero.

Construcția tabelelor hash în timp real și timp de acces este utilă într-o varietate de aplicații care necesită date rare. De exemplu, pentru aplicațiile grafice: hashing-ul spațial pentru a detecta intersecția datelor în mișcare, și hashing-ul geometric pentru funcția de potrivire. Se pare că un spațiu hash pe o rețea virtuală 1283 poate fi construit pe fiecare cadru în aproximativ 27 de cadre pe secundă. Geografia hashing este o aplicație GPU de grup care necesită acces intens intamplător la o masă de perechi de puncte caracteristice.

3 Tipuri de hashing

3.1 Hashing perfect

Ca și în multe lucrări de creare a tabelelor de hash pe GPU, ne concentrăm pe construirea unei mese ideale de tip hash. Construcția clasică a tabelului hash ideal pentru Friedman și colab. [1984] (construcția FKS) se bazează pe observația că dacă mărimea tabelului m este mult mai mare decât numărul elementelor n. mai ales dacă m = 0 (n2). atunci cu o anumită probabilitate constantă, o funcție hash selectată aleatoriu nu va avea coliziuni deloc și va da un timp constant de căutare. Pentru a obține un timp constant de căutare pentru un spațiu liniar, construcția FKS utilizează un tabel cu două nivele. La nivelul superior, elementele sunt împrăștiate în segmente, iar nivelul inferior are un segment de elemente k într-un tampon de dimensiune O (k 2). În timp ce fiecare segment are doar O (1) elemente așteptate, dimensiunea așteptată a tabelului hash este O (n) și timpul de căutare al fiecărui element O (1). Principalul dezavantaj este că pentru a obține o încărcătură optimă, spune 1/4, sunt necesare multe segmente mici.

3.2 Hashing cu opțiuni multiple (alternativă) și Hashing metoda cucului

3.3 Hacking paralel prin metoda cucului

Problema principală a paralelizării algoritmilor hash de către metoda cucului în determinarea semanticii actualizărilor maselor paralele este corectă, astfel încât coliziunile dintre elemente sunt eliminate în mod corespunzător. Algoritmul folosește trei tabele submodulare (d = 3), fiecare având dimensiunea n * (1 + γ) / 3, unde γ este o constantă suficient de mare. La prima repetare, încercăm să salvăm toate elementele din primul sub-tabel al lui T1. scriind simultan fiecare element în locul său în tabel. Semantica necesită ca exact o înregistrare să aibă succes atunci când apar coliziuni și că fiecare fir este capabil să determine această înregistrare. Acest lucru se realizează prin scrierea tuturor elementelor independent unul de celălalt și apoi prin utilizarea unui apel de sincronizare a firului astfel încât conținutul mesei să nu se modifice în timpul verificării succesului. Aproximativ 2n / 3 elemente eșuează și trebuie să fie scrise în sub-tabelul T2 la a doua iterație. Elementele care nu au putut intra în sub-tabelul T2. sunt trimise la T3. În cele din urmă, acele elemente care au eșuat în T3. reveniți la T1. împingeți niște elemente deja în sub-tabel și încercați să le luați locul. Elementele evacuate, precum și cele care nu au putut găsi un loc în T1. continuați aceleași acțiuni în T2. Iterațiile continuă până când toate elementele își găsesc locul în tabel sau până la numărul maxim de iterații și în acest caz se consideră că a fost aleasă o funcție de hash nereușită. Deși pentru d = 2 pentru un algoritm secvențial, numărul maxim așteptat de iterații este O (lg n); Este mult mai dificil să se obțină valori teoretice ale limitei superioare pentru d> 3. Cu toate acestea, în practică vedem că numărul de iterații este moderat.

Cu toate acestea, metoda hashing concomitentă prin metoda cucului nu va fi eficientă pentru construirea tabelelor hash mari pe GPU, deoarece fiecare iterație necesită amestecarea elementelor din memoria globală cu sincronizare globală la fiecare iterație. Dar acest lucru este foarte potrivit pentru mese care pot fi proiectate pentru memorie mică și rapidă încorporată în interiorul cristalului. Astfel, poate fi utilizată o metodă hibridă. Ca și în schema de construcție FKS, mai întâi găsim funcția hash a primului nivel pentru divizare în segmente mai mici. În fiecare segment, folosim cache-ul paralel prin metoda cucului pentru a plasa elementele în trei sub-tabele. Deoarece este executată complet pe memoria internă, în practică se dovedește a fi foarte rapidă.

Această secțiune descrie o implementare care utilizează arhitectura hardware și software CUDA care vă permite să efectuați calcule folosind procesoare grafice NVIDIA.

Să presupunem că intrarea este un set de elemente n - perechi cheie-valoare întreg (k, v). unde toate cheile sunt unice. Procesul de construcție este dat în Algoritmul 1 și constă din două etape.

Pasul 1 distribuie elementele între segmente folosind funcția hash h. rearanjarea datelor astfel încât elementele fiecărui segment să fie într-o zonă de memorie continuă, ceea ce îmbunătățește accesul la memoria structurii pentru faza 2.

Etapa 2 construiește tabel hash individuale paralele conform metodei cuc pentru fiecare segment folosind memoria partajată rapid, și apoi rescrie un tabel în memorie într-o singură matrice globală, chei și valori alternante.