Nvidia CUDA

NVIDIA CUDA (Compute Unified Device Architecture) is een parallelle computerplatform en programmeermodel ontwikkeld door NVIDIA. CUDA stelt ontwikkelaars in staat om hoogpresterende NVIDIA GPU's (Graphics Processing Units) te gebruiken voor algemene computertaken. Met CUDA kunnen ontwikkelaars de krachtige rekenmogelijkheden van GPU's benutten voor grootschalige parallelle berekeningen, waardoor de applicatieprestaties aanzienlijk verbeteren, vooral in gebieden zoals wetenschappelijke computing, machine learning, beeldverwerking en fysieke simulatie. CUDA ondersteunt meerdere programmeertalen, zoals C, C++ en Python, en biedt een rijke set bibliotheken en tools om ontwikkelaars te helpen gemakkelijk GPU-versnelde computing te bereiken.

cuda logo

Basisprincipes van CUDA-programmering

Hoe kunnen we GPU-resources in een programma aanroepen om code-uitvoering te versnellen? Door CUDA te gebruiken, kunnen we gemakkelijk duizenden rekenkernen binnen de GPU beheren. Het CUDA-programmeermodel is een heterogeen model dat vereist dat de CPU en GPU samenwerken. In CUDA-programmering worden de termen "host" en "device" gebruikt om de apparaten te onderscheiden waar de code wordt uitgevoerd.

  • Host: CPU en host-geheugen
  • Device: GPU en videogeheugen

Over het algemeen laadt het hoofdprogramma op de CPU, kopieert vervolgens de initialisatiegegevens naar de GPU. De GPU voert de berekeningen uit en kopieert de resultaten terug naar de CPU.

We kunnen een kernel in een CUDA-programma gebruiken om het bovenstaande proces te implementeren. In CUDA verwijst een kernel naar een functie die, wanneer aangeroepen, de GPU veroorzaakt om veel threads tegelijkertijd te starten om deze kernel uit te voeren, waardoor parallellisme wordt bereikt. Elke thread voert de kernel uit met behulp van zijn thread-ID om overeen te komen met de index van de invoergegevens, waardoor wordt gegarandeerd dat elke thread dezelfde kernel uitvoert maar verschillende gegevens verwerkt.

De GPU heeft een enorm aantal rekenkernen, en CUDA gebruikt een tweeledige organisatiestructuur om deze kernen te beheren. Hier zijn drie concepten in CUDA-programmering die moeten worden geïntroduceerd: Thread, Block en Grid.

  • Thread: Een parallel CUDA-programma wordt uitgevoerd door veel threads.
  • Block: Verschillende threads worden gegroepeerd om een blok te vormen.
  • Grid: Meerdere blokken worden vervolgens georganiseerd in een grid.

Opmerking: Threads binnen hetzelfde blok kunnen synchroniseren en communiceren via gedeeld geheugen.

cpu and gpu

In CUDA heeft elke thread een unieke identificatie genaamd ThreadIdx, die afhankelijk is van de manier waarop het Grid en Block zijn verdeeld.

Bovendien volgt hier een korte introductie van het CUDA-geheugenmodel, zoals weergegeven in het diagram hieronder. Elke thread heeft zijn eigen privé lokale geheugen, terwijl elk threadblok gedeeld geheugen bevat dat toegankelijk is voor alle threads binnen het blok, met een levensduur gelijk aan die van het threadblok. Verder kunnen alle threads toegang krijgen tot globaal geheugen. Er zijn ook enkele alleen-lezen geheugenruimtes: constant geheugen en textuurgeheugen. De geheugenstructuur heeft betrekking op programma-optimalisatie, wat hier niet in detail zal worden besproken.

cpu and gpu

CUDA demonstratievoorbeeld

Laten we nu GPU-acceleratie ervaren door een eenvoudig voorbeeld. In dit voorbeeld berekenen we de som van twee vectoren op zowel de CPU als de GPU, en vergelijken we de computatiesnelheden tussen CPU en GPU.

De runtime-omgeving voorbereiden

Het JetPack-besturingssysteem bevat al de CUDA-runtime-omgeving. We kunnen de CUDA-versie controleren met het jtop-hulpmiddel. Open de terminal en voer jtop uit.

bash
jtop

jtop

Opmerking: Als jtop niet op uw systeem is geïnstalleerd, raadpleeg dan deze handleiding.

Hieronder zullen we Python gebruiken om CUDA-code te schrijven. We moeten dus de volgende opdracht in de terminal uitvoeren om Numba te installeren.

bash
pip install numba

Het voorbeeldcode uitvoeren

Stap 1: Maak een Python-script voor deze cursus in de hoofdmap:

bash
mkdir -p ~/reComputer_J/3.4_CUDA
touch ~/reComputer_J/3.4_CUDA/add_compare.py

Stap 2: Open VSCode in de map waar het script zich bevindt:

bash
cd ~/reComputer_J/3.4_CUDA
code .

Stap 3: In de linkernavigatiebalk kunnen we hello_world.py zien. Voer de volgende code in het python-bestand in:

Klik om code uit te breiden
python
from numba import cuda, float32
import numpy as np
import time


@cuda.jit
def add_gpu(a, b, out):
  tx = cuda.threadIdx.x
  ty = cuda.blockIdx.x
  block_size = cuda.blockDim.x
  grid_size = cuda.gridDim.x
  start = tx + ty * block_size
  stride = block_size * grid_size

  for i in range(start, a.shape[0], stride):
      out[i] = a[i] + b[i]

def add_cpu(a, b, out):
  for i in range(a.shape[0]):    
      out[i] = a[i] + b[i]

def main():
  # Prepare test data
  n = 10000000
  a = np.arange(n).astype(np.float32)
  b = np.arange(n).astype(np.float32)
  out = np.empty_like(a)

  # 1. Test CPU computation time
  start = time.time()
  add_cpu(a, b, out)
  print("CPU Time Taken:", time.time()-start)

  # 2. Test GPU computation time
  # Copy data from host memory to device memory
  d_a = cuda.to_device(a)
  d_b = cuda.to_device(b)
  d_out = cuda.device_array_like(out)
  # Define the number of threads per block and the number of blocks
  threads_per_block = 256  
  blocks_per_grid = (n + threads_per_block - 1) // threads_per_block
  # Compute the result
  start_gpu = time.time()
  add_gpu[blocks_per_grid, threads_per_block](d_a, d_b, d_out)
  end_gpu = time.time()
  # Copy the result from device memory back to host memory
  d_out.copy_to_host(out)

  print("GPU Time Taken:", end_gpu-start_gpu)


if __name__ == "__main__":
  main()

Stap 4: Klik op de uitvoerknop om het resultaat van het Python-script in de terminal te zien.

launch vscode

Uit de resultaten in de terminal kan worden waargenomen dat de GPU-computatiesnelheid sneller is.

Meer CUDA-leertutorials

TutorialTypeBeschrijving
Getting Started with CUDA Programming(zh)DocumentEen minimalistische tutorial om aan de slag te gaan met CUDA-programmering in het Chinees
CUDA C++ Programming GuideDocumentDe programmeerhandleiding voor het CUDA-model en de interface.