Thread Hierarchy, CUDA Kernel
CUDA

Thread Hierarchy, CUDA Kernel

๐Ÿ’ก Thread Hierarchy

  • ์ปค๋„ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ŠคํŠธ์—์„œ ํ˜ธ์ถœ๋  ๋•Œ, ๋งŽ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋จ
  • ์Šค๋ ˆ๋“œ ๊ณ„์ธต ๊ตฌ์กฐ๋Š” ์Šค๋ ˆ๋“œ ๋ธ”๋ก๊ณผ ๊ทธ๋ฆฌ๋“œ๋กœ ๊ตฌ์„ฑ๋จ
  • ์–ด๋–ค ์Šค๋ ˆ๋“œ๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ• ์ง€ ์ธ๋ฑ์‹ฑ์„ ํ•ด์ฃผ๋Š”๊ฒŒ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ํ•ด์•ผํ•  ์—ญํ• ์ž„
  • ๊ทธ๋ฆฌ๋“œ์™€ ์Šค๋ ˆ๋“œ ๋ธ”๋ก์˜ ํฌ๊ธฐ๋Š” ๋‘ ๊ฐœ์˜ built-in ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌํ•  ์ˆ˜ ์žˆ์Œ
  • gridDim:๊ทธ๋ฆฌ๋“œ ํฌ๊ธฐ(๊ทธ๋ฆฌ๋“œ ๋‚ด์˜ ๋ธ”๋ก์˜ ์ˆ˜), gridDim.x, gridDim.y, grindDim.z
  • blockDim: ๋ธ”๋ก์˜ ํฌ๊ธฐ(๋ธ”๋ก ๋‚ด์˜ ์Šค๋ ˆ๋“œ์˜ ์ˆ˜), blockDim.x, blockDim.y, blockDim.z
  • blockIdx: ๊ทธ๋ฆฌ๋“œ ๋‚ด์—์„œ ๋ธ”๋ก ์ธ๋ฑ์Šค
  • threadIdx: ๋ธ”๋ก ๋‚ด์—์„œ ์Šค๋ ˆ๋“œ ์ธ๋ฑ์Šค
  • ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜=์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜= ๋ธ”๋ก์˜ ํฌ๊ธฐ * ๊ทธ๋ฆฌ๋“œ์˜ ํฌ๊ธฐ
  • ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๋ณด๋‹ค ์กฐ๊ธˆ ๋” ํฌ๋„๋ก ๊ตฌ์„ฑํ•˜๋ฉด ๋จ
  • ๊ธ€๋กœ๋ฒŒ ์ธ๋ฑ์Šค int idx = blockDim.x*blockIdx.x+threadIdx.x

 

๐Ÿ’ก CUDA Kernel

  • ์ปค๋„ ํ•จ์ˆ˜๋Š” ๋””๋ฐ”์ด์Šค์—์„œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ
  • ์ปค๋„ ํ•จ์ˆ˜์—์„œ๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ๊ณ„์‚ฐ์„ ์ •์˜ํ•˜๊ณ  ํ•ด๋‹น ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์„ ์ •์˜
  • ์ปค๋„์€ __global__ ์„ ์–ธ ํ•œ์ •์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์˜๋จ
  • ์ปค๋„ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ void return tyoe ์ด์–ด์•ผ ํ•จ
  • ์ปค๋„ ํ˜ธ์ถœ ์‹œ ๊ทธ๋ฆฌ๋“œ์™€ ์Šค๋ ˆ๋“œ ๋ธ”๋ก์˜ ํฌ๊ธฐ๋ฅผ <<<>>>์•ˆ์— ์ง€์ •, kernel_name<<<grid, block>>>(argument list);
  • argument์— ๋“ค์–ด๊ฐ€๋Š” ๋ณ€์ˆ˜๋“ค์€ GPU์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์žˆ์–ด์•ผ ํ•จ
  • ์ปค๋„ ํ˜ธ์ถœ์€ ํ˜ธ์ŠคํŠธ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•ด ๋น„๋™๊ธฐ์ ์ž„ -> GPUํ•œํ…Œ ์ž‘์—…์„ ๋„˜๊ฒจ์ฃผ๊ณ  CPU๋Š” ๋‹ค์Œ ์ค„๋กœ ๋„˜์–ด๊ฐ
  • cudaDeviceSynchronize ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ–๋Š” ์ž‘์—…์— ๋Œ€ํ•ด ๋™๊ธฐํ™”๋ฅผ ์ง„ํ–‰ํ•ด์ฃผ์–ด์•ผ ํ•จ
  • ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚œ ๋’ค ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๊ธฐ ์ „์— cudaDeviceReset์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํ• ๋‹นํ–ˆ๋˜ ์ž์›๋“ค์„ ํ•ด์ œํ•ด์ฃผ๊ณ  synchronize ๊ธฐ๋Šฅ๋„ ์ˆ˜ํ–‰ํ•ด์ฃผ์–ด์•ผ ํ•จ
#include <stdio.h>

__global__ void GPUKernel(int arg){
        printf("Input Value (on GPU) = %d \n", arg);
}
int main(void){
        printf("Call Kernel Function \n");

        GPUKernel<<<1,1>>>(1);
        GPUKernel<<<1,1>>>(2);
        cudaDeviceSynchronize();

        return 0;
}

๊ฒฐ๊ณผ

Call Kernel Function
Input Value (on GPU) = 1
Input Value (on GPU) = 2

 

#include <stdio.h>
__host__ __device__ void Print(){
        printf("Hello from Print()\n");
}
__global__ void Wrapper(){
        Print();
}
int main(void){
        Print();//from host
        printf("===============\n");
        Wrapper<<<1,5>>>();
        cudaDeviceReset();
        return 0;
}

๊ฒฐ๊ณผ

Hello from Print()
===============
Hello from Print()
Hello from Print()
Hello from Print()
Hello from Print()
Hello from Print()

๐Ÿ’ก 2์ฐจ์›

1์ฐจ์›์ผ ๋•Œ๋Š” thred ๊ฐœ์ˆ˜๋งŒ ์ฃผ๋ฉด ๋˜์ง€๋งŒ, 2์ฐจ์›๋ถ€ํ„ฐ๋Š” index ์ž์ฒด๋„ 2์ฐจ์›์œผ๋กœ ํ‘œํ˜„์ด ๋œ๋‹ค.
xํ•˜๊ณ  y๋Š” ๋…๋ฆฝ์ ์ธ ์ถ•์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์„œ local index๋ฅผ ์ด์šฉํ•˜์—ฌ x์™€ y์— ๋Œ€ํ•œ global index๋ฅผ ๊ตฌํ•˜๋ฉด ๋œ๋‹ค.

2์ฐจ์› ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ณ„์‚ฐ ์ˆœ์„œ์™€ ๋ฃจํ”„์— ๋”ฐ๋ผ ์บ์‹œ๊ฐ€ ๋ฐฐ์—ด์— ์–ด๊ธ‹๋‚˜์„œ ์„ฑ๋Šฅ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์บ์‹œ ๋ฏธ์Šค๋ผ๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์บ์‹œ ๋ฏธ์Šค๋ฅผ ์‚ฌ์ „์— ์ฐจ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ๋Š” ์ฃผ๋กœ 1์ฐจ์› array๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, row์™€ col์„ ํ†ตํ•ด์„œ 1์ฐจ์› ์ƒ์˜ index๋ฅผ ๊ตฌํ•œ๋‹ค. index๋ฅผ ๊ตฌํ•˜๋Š” ๋ฒ•์€ ๋ฐ‘์˜ ์ฝ”๋“œ ์˜ˆ์ œ์™€ ๊ฐ™๋‹ค

__device__ int getGlobalIdx_2D(const int N){
    int col = blockIdx.x*blockDim.x+thredIdx.x;
    int row = blockIdx.y*blockDim.y+thredIdx.y;
    
    int index = col+row*N;
    
    return index;
}

 ์ปค๋„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๊ทธ๋ฆฌ๋“œ์˜ ํฌ๊ธฐ์™€ ๋ธ”๋ก์˜ ํฌ๊ธฐ๋ฅผ ์ •ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ ๊ณฑํ•˜๊ธฐ๋กœ ๋”ฑ ๋–จ์–ด์ง€์ง€ ์•Š๋Š” ์ˆซ์ž์ธ ๊ฒฝ์šฐ์—๋Š” ์กฐ๊ธˆ ๋” ํฐ thread ๊ฐœ์ˆ˜๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ thread ๊ฐœ์ˆ˜๊ฐ€ ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๋ณด๋‹ค ์กฐ๊ธˆ ๋งŽ์€ ๊ฒฝ์šฐ์—๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” thread๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋•Œ ๋น„์–ด์žˆ๋Š” thread์—์„œ ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์œผ๋กœ ์ ‘๊ทผ์„ ํ•ด์„œ segmentation fault ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์˜ˆ์ œ๋Š” ๋ฐ‘์˜ ์ฝ”๋“œ์ด๋‹ค.

template <int col> __global__ vpod AddMatOnGPU(float *A, float *B, float *C, int M, int N){
	int idx_x=blockIdx.x*blockDim.x+threadIdx.x;
	int idx_y=blockIdx.y*blockDim.y+threadIdx.y;
    float (*pA)[col]=(float (*)[col])A;
    float (*pB)[col]=(float (*)[col])B;
    float (*pC)[col]=(float (*)[col])C;
    if(idx_x<N && idx_y<M) pC[idx_y][idx_x] = pA[idx_y][idx_x]+pB[idx_y][idx_x];//์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถ€๋ถ„
}

๊ฐ•์˜

kisti.re.kr

'CUDA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

GPU Architecture, CUDA Compiler  (0) 2024.02.14
CUDA, ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ  (0) 2024.02.13