CUDA - 10 tutoriali dla początkujących

Podstawy programowania równoległego z użyciem CUDA

View the Project on GitHub Kowalikov/CUDA_blogs

I. CUDA C++: Ustawienie środowiska CUDA na Windowsie i Linuxie

Autor: Natan Jarzyński

Słowa kluczowe: GPU programming, programming, coding, CUDA toolkit, CUDA, C++, GPU, programowanie równoległe, instalacja CUDA, pierwszy program CUDA, alokacja pamięci GPU, kernel CUDA, nvcc, nvidia-smi


CUDA w C++ - od instalacji do pierwszego programu

W pierwszej części tej serii pokażemy, jak przygotować środowisko programistyczne do pracy z CUDA w C++, a następnie napiszemy i uruchomimy prosty program, który podnosi liczby do kwadratu na karcie graficznej NVIDIA.

🧰 Krok 1: Instalacja CUDA Toolkit

Upewnij się, że masz kompatybilną kartę graficzną NVIDIA (np. z serii GeForce, Quadro, Tesla).

  1. Przejdź na stronę pobierania CUDA toolkit: https://developer.nvidia.com/cuda-toolkit
  2. Wybierz swój system operacyjny (Windows, Linux):
    • Windows: Najprostszym sposobem w naszej opinii, jest skorzystanie z pakietu CUDA dla Windows, który zawiera wszystkie niezbędne komponenty, w tym sterowniki i narzędzia programistyczne.
    • Linux: Na Linuxie możesz skorzystać z menedżera pakietów (np. apt na Ubuntu) lub pobrać instalator ze strony NVIDIA.

      Pamiętaj, że na Linuxie może być konieczne ręczne zainstalowanie sterowników NVIDIA przed instalacją CUDA Toolkit.

      Z naszego doświadczenia, na linuxie najlepiej jest użyć Ubuntu 22.04/24.04 LTS, które są szeroko wspierane przez NVIDIA i mają dobre wsparcie dla sterowników i narzędzi CUDA.

      Możesz na swoim Windowsie postawić Ubuntu 24.04 LTS, przez WSL (Windows Subsystem for Linux), co pozwoli Ci korzystać z narzędzi Linuxowych i jednocześnie mieć dostęp do GPU NVIDIA. Zazwyczaj GPU jest dostępna w WSL automatycznie w nowszych Windowsach. W przypadku braku automatycznej integracji, konfiguracja WSL z obsługą GPU może być nieco bardziej skomplikowana niż tradycyjna instalacja na natywnym Linuxie, ale jest to świetna opcja dla programistów, którzy chcą korzystać z obu środowisk, mimo wszystko. Tutaj instrukcja do postawienia Ubuntu 24.04 LTS przez WSL.

  3. Pobierz i zainstaluj:
    • [Jeżeli nie są zainstalowane, jeżeli są, nie ruszaj!] Sterowniki NVIDIA (upewnij się, że są aktualne)
    • CUDA Toolkit (zawiera kompilator nvcc, biblioteki, przykłady)

📌 Po instalacji sprawdź wersję CUDA:

nvcc --version

📌 Sprawdź, czy karta graficzna jest widoczna:

nvidia-smi

🧱 Krok 2: Konfiguracja środowiska

Możesz używać dowolnego edytora kodu, np.:

🧪 Krok 3: Test z pierwszym programem CUDA

Poniżej znajduje się kod, który:

📦 Kod źródłowy z komentarzami

Jest to prosty skrypt w CUDA C++, który pokazuje, jak alokować pamięć na GPU, kopiować dane, uruchamiać kernel i synchronizować wyniki. Potraktujemy go jako “sanity check” — czyli podstawowy test, który pozwoli nam upewnić się, że środowisko CUDA jest poprawnie skonfigurowane i że możemy uruchamiać programy na GPU. W kolejnych częściach będziemy omawiać już określone funkcjonalności w szczególe. Rzuć okiem na kod i jego komentarze, a następnie wklej go do pliku kernel.cu i uruchom go na swoim komputerze z GPU NVIDIA, za pomocą komendy nvcc.

#include <iostream>                      
#include <cuda_runtime.h>               // Główna biblioteka CUDA do zarządzania pamięcią i urządzeniem
#include <device_launch_parameters.h>   // Parametry uruchamiania kernela (np. blockIdx, threadIdx)

// Kernel uruchamiany na GPU — każdy wątek podnosi jeden element tablicy do kwadratu
__global__ void squareKernel(int* x, int n) {
    // Obliczenie globalnego indeksu wątku w siatce
    int i = blockIdx.x * blockDim.x + threadIdx.x;

    // Sprawdzenie, czy indeks mieści się w zakresie tablicy
    if (i < n) {
        x[i] = x[i] * x[i];  // Podniesienie wartości do kwadratu
    }
}

int main() {
    const int size = 100;  // Rozmiar tablicy
    int* host_x = new int[size];  // Dynamiczna alokacja pamięci na CPU (na stercie)

    // Inicjalizacja tablicy wartościami od 0 do 99
    for (int i = 0; i < size; ++i)
        host_x[i] = i;

    // Alokacja pamięci na GPU (device)
    int* device_x;
    cudaMalloc(&device_x, size * sizeof(int));

    // Kopiowanie danych z CPU (host) do GPU (device)
    cudaMemcpy(device_x, host_x, size * sizeof(int), cudaMemcpyHostToDevice);

    // Uruchomienie kernela: 20 bloków po 5 wątków = 100 wątków
    squareKernel <<< 20, 5 >>> (device_x, size);

    // Synchronizacja — czekamy aż GPU zakończy pracę
    cudaDeviceSynchronize();

    // Sprawdzenie, czy kernel wykonał się poprawnie
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        std::cerr << "Blad kernela: " << cudaGetErrorString(err) << "\n";
        delete[] host_x;  // Zwolnienie pamięci na CPU
        return 1;
    }

    // Kopiowanie wyników z GPU z powrotem do CPU
    cudaMemcpy(host_x, device_x, size * sizeof(int), cudaMemcpyDeviceToHost);

    // Wypisanie wyników na konsolę
    for (int i = 0; i < size; ++i)
        std::cout << "x[" << i << "] = " << host_x[i] << "\n";

    // Zwolnienie pamięci na GPU i CPU
    cudaFree(device_x);
    delete[] host_x;

    return 0;
}

Na linuxie możesz użyć terminala (kompilując program, dodając uprawnienia do wykonania skompilowanego pliku i uruchamiając go):

nvcc kernel.cu -o kernel 
chmod u+x ./kernel
./kernel

a na Windowsie PowerShell lub CMD:

nvcc kernel.cu -o kernel.exe
.\kernel.exe

Zapisz sobie te komendy! Będziesz z nich korzystać co sekundę, gdy będziesz pisać i testować programy CUDA.

🧠 Najważniejsze elementy skryptu ⬆️

🔍 Podsumowanie

W tym tutorialu w 3 krokach pokazaliśmy, jak zacząć używać CUDA Toolkit i przetestować z prostym programem w CUDA C++. W kolejnych częściach zagłębimy się w szczegóły programowania równoległego z CUDA.


Strona główna

Następny wpis: II. Sprawdzanie środowiska CUDA