HOME ABOUT CONTACT

技術(Python) - CUDA 重點整理和範例

Rain April 12, 2025
Outline

1. CUDA 簡介

2. Kernel

3. Thread Hierarchy

4. Memory Hierarchy

5. Python 範例

CUDA 簡介 top

CUDA 是一套運用 GPU 大量核心的程式語法和介面,讓程式碼由 GPU 的多執行緒來執行,藉此來達到比 CPU 更加快速的執行效能。

Kernel top

Kernel 就相當於我們所學的函式(Function),只是這個函式是由 GPU 來執行的,因此在定義這個函式時,需要用 CUDA 的巨集來修飾函式,讓編譯器知道這段函式內容是由 GPU 來執行,而通常 Kernel 處理的對象會是 Vector、Array 或 Matrix。

我們來看看 C/C++ 和 Python 範例:

C/C++:

__global__ void vector_addition(float* a, float* b, float* c)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}

int main()
{
    ...
    vector_addition<<<1, N>>>(a, b, c) // Kernel invocation with N threads
    ...
}
                    
Python:

@jit(nopython=True)
def vector_addition(a, b, c):
    int i = threadIdx.x;
    c[i] = a[i] + b[i];

vector_addition(a, b, c)
                    

Thread Hierarchy top

執行緒可以是一維、二維或三維,這些都統稱為 thread block,而一個 thread block 預期會常駐於在相同匯流的多處理器核心之中,且它們必須共享限制的記憶體資源,在當今的GPU中,一個 thread block 可擁有1024條執行緒,總執行緒數量為 thread block 含有的執行緒 * thread block 數量。

多個 thread block 可構成一個 grid,block 的數量通常由處理的資料大小來做決定,通常數量會大於系統中的處理器數量。

Memory Hierarchy top

執行緒群會存取多個記憶體空間,每個執行緒擁有自己私有的區域記憶體。每個 thread block 都有共享記憶體,所有在 block 內的執行緒都可使用,且共享記憶體的生命週期與 block 相同。所有執行緒都可存取相同的全域記憶體。

CUDA Memory Hierarchy (圖片來源: CUDA C++ Programming Guide pdf)

Python 範例 top

Python 要實現 CUDA 可依據不同 Package 有不同的實現方式,這裡我就以 numba 這個 package 為例,用 CUDA 將圖片背景透明化。


import numpy as np
from PIL import Image
from numba import jit, cuda

def CUDA_Init(img_np):
    self.threads_per_block = (16, 16)
    self.blocks_per_grid_x = (img_np.shape[0] + self.threads_per_block[0] - 1) // self.threads_per_block[0]
    self.blocks_per_grid_y = (img_np.shape[1] + self.threads_per_block[1] - 1) // self.threads_per_block[1]

@cuda.jit
def perspective_background(img_np):
    width, height = img_np.shape[0], img_np.shape[1]
    x, y = cuda.grid(2)
    for x in range(0, width):
        for y in range(0, height):
            r, g, b = img_np[x][y][0], img_np[x][y][1], img_np[x][y][2]
            if r <= 10 and g <= 10 and b <= 10:
                img_np[x][y][3] = 0

img = Image.open("image.jpg")
img_np = np.array(img.convert("RGBA"), dtype=np.uint8)

CUDA_Init(img_np)

d_img = cuda.to_device(img_np) # 將圖像的 numpy array 載入到 GPU device
perspective_background[(self.blocks_per_grid_x, self.blocks_per_grid_y), self.threads_per_block](d_img)

result_img_np = d_img.copy_to_host() # 將處理完成的圖片讀取回來
                    

Last updated:

Related Article List

  1. CAD工作對應徵EDA職缺有哪些幫助
  2. CAD工程師在做什麼
  3. 什麼是GDSII Stream Format
  4. 技術(Python) - PySide實作PyOpenGL繪製的基本架構
  5. 技術(Python) - 3D Brain Viewer