Bazı Kavramlar

  • CPU: Az sayıda gelişmiş çekirdekleri ihtiva eder
  • GPU: Çok sayıda az gelişmiş çekirdekleri ihtiva eder
  • CUDA: NVIDIA GPU’ları üzerinde hesaplama yapmamızı sağlayan bir hede
  • GPU nedir? Grafik kartıdır.
  • GPU ne yapar? Ekrandaki piksellerin rengini hesaplamak için aynı kodu farklı çekirdeklerde milyonlarca kez çalıştırır.
  • Peki grafik kartı bilimsel hesaplamalarda ne işe yarayacak?
    Pikseli hesaplamak için matematik yapıyoruz. Bilimsel hesaplamalarda da matematik yapıyoruz. O zaman pikseli hesaplamak için kullandığımız donanımı bilimsel hesaplama için de kullanabiliriz.
  • Neden GPU?
    • The NVIDIA GeForce RTX 5060 (Desktop) features a base core clock of 2280 MHz, a boost clock of 2497 MHz, and 3840 CUDA core count.
    • Core Ultra 7 270K Plus — Packs 24 cores (8 Performance + 16 Efficiency) hitting boosts up to 5.5 GHz
    • Yani çok sayıda basit işlemi yapmak istiyorsak GPU daha avantajlı
  • Heterogeneous computing: Farklı tipte hesaplama araclarının aynı anda kullanılması: misal CPU ile GPU
  • Host code: CPU tarafında çalışan kod
  • Device code: GPU tarafında çalışan kod

Kurulum

  • Google’a NVIDIA CUDA Toolkit yazıp çıkan siteden kendi sisteminize uygun olan talimatları uygulayıp kurabilirsiniz.
  • Öncesinde driverları güncellemek faydalı olabilir.
  • Kurulum sonrası PATH değişkenini eklemek gerekebilir.
  • Benim sistem fedora ve eski bir bilgisayar. Yeni cuda sürümünü kuramadığım için eskisini kurmak durumunda kaldım. Biraz zorladı. Yapay zeka bu konuda baya işime yaradı.

Hello CUDA

#include <cstdio>

__global__ void hello()
{
    // Device code
    printf("Hello from GPU! thread=%d\n", threadIdx.x);
}

int main()
{
    // Host code 
    hello<<<1, 4>>>();
    cudaError_t err = cudaDeviceSynchronize();

    if (err != cudaSuccess)
    {
        printf("CUDA error: %s\n", cudaGetErrorString(err));
        return 1;
    }

    return 0;
}
C++
  • __global__ : GPU üzerinde çalışacak fonksiyonumuz.
  • hello <<<1, 4>>>() : asekron fonksiyon çağrısı. Yani GPU’ya sen bu fonksiyonu çalıştır diyip beklemeden devam ediyor.
  • cudaDeviceSynchronize() : GPU’nun işini bitirmesini bekle daha devam etme.
  • cudaError_t : Error code
  • cudaGetErrorString : verilen error code’un açıklama string’ini döndürür.
  • threadIdx.x : hangi thread’de olduğumuz.

Şimdi <<< >>> olayına gelelim

fonksiyon_adı<<<grid_dimension, block_dimension>>>(arguments);
C++
  • grid_dimension : Bir grid’de kaç tane block olacağı
  • block_dimension : Bir block’da kaç tane thread olabileceği

direk N tane thread çalışsın demek yerine bu şekilde bölerek dağıtıyoruz. Bu biraz donanımsal bir mesele.

Grid
├── Block
│ ├── Thread
│ ├── Thread
│ └── …
├── Block
│ ├── Thread
│ └── …
└── …

burada tek boyutlu dimension kullanıyoruz ama 2-3 boyutlu da yapabiliriz. Misal bir resmi işlerken 26. pixel yerine 27. satırdaki 14. pixel daha kullanışlı

dim3 grid_dim = dim3(1, 1, 1);
dim3 block_dim = dim3(27, 14, 1);
hello<<<grid_dim, block_dim>>>();
C++

Burada sınırlarımız sonsuz değil. Misal benim makinamda şöyle:

GPU: NVIDIA GeForce GTX 950M
Max threads/block: 1024
Max block dimensions: 1024 x 1024 x 64
Max grid dimensions: 2147483647 x 65535 x 65535

Bunları sorgulamak için şu kodu kullanıyoruz:

    cudaDeviceProp prop;

    cudaGetDeviceProperties(&prop, 0);

    printf("GPU: %s\n", prop.name);
    printf("Max threads/block: %d\n", prop.maxThreadsPerBlock);

    printf("Max block dimensions: %d x %d x %d\n",
        prop.maxThreadsDim[0],
        prop.maxThreadsDim[1],
        prop.maxThreadsDim[2]);

    printf("Max grid dimensions: %d x %d x %d\n",
        prop.maxGridSize[0],
        prop.maxGridSize[1],
        prop.maxGridSize[2]);
C++

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *