Pourquoi utiliser le GPU ?

Le calcul des empreintes cryptographiques (hashing) represente plus de 80% du temps de traitement en deduplication. Les GPUs, avec leurs milliers de coeurs paralleles, sont idealement adaptes a cette tache.

Comparaison CPU vs GPU pour le hachage
flowchart LR subgraph CPU["Traitement CPU"] direction TB C1["Core 1
Hash bloc 1"] C2["Core 2
Hash bloc 2"] C3["Core 3
Hash bloc 3"] C4["Core 4
Hash bloc 4"] CSEQ["Sequentiel
4 blocs/cycle"] end subgraph GPU["Traitement GPU"] direction TB G1["1024 threads
Hash blocs 1-1024"] G2["1024 threads
Hash blocs 1025-2048"] GPAR["Parallele
2048 blocs/cycle"] end CPU --> |"~800 MB/s"| RES1["Resultat"] GPU --> |"~18 GB/s"| RES2["Resultat"] style CPU fill:#7f1d1d,stroke:#ef4444 style GPU fill:#14532d,stroke:#22c55e

Gain de performance

Sur un GPU moderne (RTX 4090), DRAGON atteint un debit de hachage 20 a 25 fois superieur a un CPU haut de gamme, tout en consommant moins d'energie par octet traite.

Metrique CPU (i9-13900K) GPU (RTX 4090) Ratio
Coeurs de calcul 24 (8P + 16E) 16,384 CUDA 683x
Bande passante memoire 89.6 GB/s 1,008 GB/s 11x
Debit XXH3-128 ~12 GB/s ~180 GB/s 15x
Debit SHA-256 ~0.8 GB/s ~18 GB/s 22x
TDP 253W 450W 1.8x
Efficacite (GB/s/W) 0.047 0.040 ~1x

GPU Scheduler

Le GPU Scheduler est le composant central qui gere l'ordonnancement et la repartition du travail entre les GPUs disponibles.

Cycle de vie d'un WorkBlock
stateDiagram-v2 [*] --> Created: new WorkBlock Created --> Queued: submit() Queued --> Dispatched: dispatch() Dispatched --> Processing: worker.process() Processing --> Completed: success Processing --> Failed: error/timeout Failed --> Queued: retry < max Failed --> Abandoned: retry >= max Completed --> [*] Abandoned --> [*] note right of Queued FIFO avec priorite Trie par taille fichier end note note right of Dispatched Worker selectionne par: - Disponibilite - Metriques perf - Localite end note note right of Failed Causes: timeout, OOM Worker exclu pour ce bloc Retry sur autre worker end note

Selection du worker optimal

Algorithme de dispatch

  1. Filtrage : Exclure les workers indisponibles ou deja en echec pour ce bloc
  2. Score de performance : Pour chaque worker candidat, calculer :
    • Temps estime = latence + (taille / debit)
    • Penalite si queue locale > seuil
    • Bonus si local (vs remote)
  3. Selection : Choisir le worker avec le meilleur score
  4. Dispatch : Envoyer le bloc et demarrer le timer de timeout
Formule de calcul du timeout
flowchart LR subgraph Inputs["Parametres"] LAT["latency_ms
(moyenne glissante)"] COMP["compute_time_per_mb
(moyenne glissante)"] THR["throughput_mb_s
(moyenne glissante)"] SIZE["block_size_mb"] end subgraph Formula["Calcul"] F1["transfer_time = size / throughput"] F2["compute_time = size * compute_per_mb"] F3["base = 2*latency + transfer + compute"] F4["timeout = base * multiplier"] end subgraph Output["Resultat"] TO["timeout_ms
(avec marge 2.5x)"] end Inputs --> Formula Formula --> Output

Metriques et adaptation

Le scheduler maintient des metriques en temps reel pour chaque worker, permettant une adaptation dynamique aux conditions reelles.

Metriques suivies

  • latency_ms : Temps de round-trip
  • throughput_mb_sec : Debit effectif
  • compute_time_per_mb : Temps calcul/MB
  • blocks_processed : Compteur blocs
  • bytes_processed : Compteur octets
  • error_count : Nombre d'erreurs

Moyenne glissante

Les metriques utilisent un lissage exponentiel :

Formule EMA

nouvelle_valeur = (1 - alpha) * ancienne + alpha * mesure

avec alpha = 0.3 (smoothing factor)

Avantages : reactive aux changements tout en filtrant le bruit.

Gestion memoire GPU

La memoire GPU est une ressource limitee et precieuse. DRAGON optimise son utilisation pour maximiser le debit tout en evitant les erreurs OOM.

Strategie d'allocation memoire
flowchart TB subgraph GPU_MEM["Memoire GPU (24 GB)"] subgraph Reserved["Reserve Systeme (30%)"] SYS["~7 GB"] end subgraph Available["Disponible DRAGON (70%)"] subgraph Buffers["Buffers d'Entree"] B1["Buffer 1
64 MB"] B2["Buffer 2
64 MB"] B3["Buffer 3
64 MB"] BN["..."] end subgraph Output["Buffers de Sortie"] O1["Hashes"] O2["Results"] end subgraph Index["Index GPU"] BLOOM["Bloom Filter
~256 MB"] BTREE["B+Tree Cache
~1 GB"] end end end style Reserved fill:#7f1d1d,stroke:#ef4444 style Available fill:#14532d,stroke:#22c55e

Algorithme de gestion memoire

  1. Detection : Interroger la memoire GPU disponible au demarrage
  2. Reservation : Garder 30% pour le systeme et autres applications
  3. Allocation : Pre-allouer les buffers (pool) pour eviter la fragmentation
  4. Dimensionnement : Ajuster la taille des blocs selon la memoire :
    • < 4 GB : blocs de 1-16 MB max
    • 4-8 GB : blocs de 1-32 MB max
    • > 8 GB : blocs de 1-64 MB max
  5. Recyclage : Reutiliser les buffers liberes (ring buffer)

Hachage parallele

Le coeur de l'acceleration GPU est le calcul parallele des empreintes cryptographiques sur des milliers de chunks simultanement.

Pipeline de hachage GPU
sequenceDiagram participant CPU as CPU Host participant BUF as Buffer GPU participant KERN as Kernel Hash participant OUT as Output GPU Note over CPU,OUT: Phase 1: Transfert Host -> Device CPU->>BUF: cudaMemcpyAsync(data, 64MB) Note over CPU,OUT: Phase 2: Execution Kernel BUF->>KERN: Launch hash_kernel KERN->>KERN: Chaque thread hash 1 chunk (16KB) KERN->>OUT: Ecriture hash 256-bit Note over CPU,OUT: Phase 3: Transfert Device -> Host OUT->>CPU: cudaMemcpyAsync(hashes) Note over CPU,OUT: Pipeline: N blocs en vol simultanes

Organisation des threads

Mapping threads / chunks
flowchart TB subgraph Block64MB["WorkBlock 64 MB"] subgraph Chunks["4096 chunks de 16 KB"] C1["Chunk 0"] C2["Chunk 1"] C3["Chunk 2"] CN["..."] C4095["Chunk 4095"] end end subgraph GPU_Exec["Execution GPU"] subgraph Grid["Grid: 16 blocks"] subgraph TB1["Thread Block 0
256 threads"] T0["Thread 0
-> Chunk 0"] T1["Thread 1
-> Chunk 1"] T255["Thread 255
-> Chunk 255"] end subgraph TB2["Thread Block 1
256 threads"] T256["Thread 256
-> Chunk 256"] end TBN["..."] subgraph TB16["Thread Block 15
256 threads"] T3840["Thread 3840
-> Chunk 3840"] end end end Block64MB --> GPU_Exec
Parametre Valeur Justification
Threads par block 256 Optimal pour occupancy sur SM
Chunks par thread 1 Simplicity, bon pour memoire coalescee
Taille chunk min 4 KB Granularite fine pour CDC
Taille chunk max 64 KB Limite superieure pour dedup efficace
Streams CUDA 4 Pipeline transfert + compute

Optimisations de performance

Transferts asynchrones

Utilisation de streams CUDA multiples pour recouvrir les transferts memoire avec le calcul.

gantt title Pipeline GPU (4 streams) dateFormat X axisFormat %s section Stream 0 Transfer H2D :a1, 0, 2 Compute :a2, after a1, 3 Transfer D2H :a3, after a2, 1 section Stream 1 Transfer H2D :b1, 1, 2 Compute :b2, after b1, 3 Transfer D2H :b3, after b2, 1 section Stream 2 Transfer H2D :c1, 2, 2 Compute :c2, after c1, 3 Transfer D2H :c3, after c2, 1

Memoire coalescee

Organisation des donnees pour que les threads adjacents accedent a des adresses memoire contigues.

  • Chunks alignes sur 128 bytes
  • Padding pour eviter bank conflicts
  • Prefetch des donnees en shared memory

Batching intelligent

Regroupement des petits fichiers en batches pour amortir le cout de lancement des kernels.

  • Fichiers < 10 MB : accumulation
  • Batch size cible : 64 MB
  • Flush si timeout 100ms

Zero-copy quand possible

Pour les GPUs integres ou avec memoire unifiee, eviter les copies explicites.

  • Detection automatique UMA
  • Pinned memory pour DMA
  • Mapped memory pour acces direct

Benchmarks

Debit de hachage par GPU
xychart-beta title "Debit SHA-256 (GB/s)" x-axis ["GTX 1080", "RTX 2080", "RTX 3080", "RTX 3090", "RTX 4080", "RTX 4090"] y-axis "GB/s" 0 --> 20 bar [3.5, 6.2, 12.0, 14.5, 15.8, 18.2]
Temps de traitement pour 1 TB
xychart-beta title "Temps (minutes)" x-axis ["CPU seul", "GTX 1080", "RTX 3080", "RTX 4090", "2x RTX 4090"] y-axis "Minutes" 0 --> 25 bar [21, 5.8, 1.6, 0.9, 0.5]
Configuration Debit 1 TB 10 TB
CPU seul (i9-13900K) 0.8 GB/s 21 min 3.5 h
1x RTX 5090 (local) 24 GB/s 42 sec 7 min
1x GB10 (distribue) 18 GB/s 55 sec 9.2 min
1x RTX 3080 (distribue) 12 GB/s 1.4 min 14 min

Pour aller plus loin