๐ก 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];//์์ธ ์ฒ๋ฆฌ ๋ถ๋ถ
}
๊ฐ์
'CUDA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
GPU Architecture, CUDA Compiler (0) | 2024.02.14 |
---|---|
CUDA, ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ (0) | 2024.02.13 |