๐ต ์บ์ ํํธ์ ์ญ์ค
๊ฐ์
์ฒซ ๋ฒ์งธ ํ๋กํ์ผ๋ง ํ์ ์ฌ๊ฑด์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค! ์ธ ๊ฐ์ GPU ์ปค๋์ด ๋ชจ๋ ๋์ผํ ๋ฒกํฐ ๋ง์
output[i] = a[i] + b[i]์ ์ํํฉ๋๋ค. ๋น์ฐํ ์ฑ๋ฅ๋ ๊ฐ๊ฒ ์ฃ ?
์๋๋๋ค! ์ด ์ปค๋๋ค์ ์ฑ๋ฅ ์ฐจ์ด๋ ๊ทน์ ์ ๋๋ค - ํ๋๋ ๋๋จธ์ง๋ณด๋ค ์์ญ ๋ฐฐ๋ ๋๋ฆฝ๋๋ค. ์ฌ๋ฌ๋ถ์ ์๋ฌด: ๋ฐฉ๊ธ ๋ฐฐ์ด ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ ์ ๊ทธ๋ฐ์ง ๋ฐํ๋ด์ธ์.
๋์ ๊ณผ์
GPU ์ต์ ํ์ ๋ํ ๊ธฐ์กด ์์์ ์์ ํ ๋ค์ง๋ ์ฑ๋ฅ ๋ฏธ์คํฐ๋ฆฌ์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค! ๋์์๋ ๊ฒ๋ณด๊ธฐ์ ๋์ผํ ๋ฒกํฐ ๋ง์ ์ปค๋ ์ธ ๊ฐ๊ฐ ์๊ณ , ๋ชจ๋ ์ ํํ ๊ฐ์ ์ํ ์ฐ์ฐ์ ์ํํฉ๋๋ค:
output[i] = a[i] + b[i] // ๋จ์ํ ์ฐ์ ์ฐ์ฐ - ๋ญ๊ฐ ์๋ชป๋ ์ ์์๊น?
์ถฉ๊ฒฉ์ ์ธ ํ์ค:
- ์ธ ์ปค๋ ๋ชจ๋ ๋์ผํ๊ณ ์ ํํ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํฉ๋๋ค
- ํ๋์ ์ปค๋์ด ๋๋จธ์ง๋ณด๋ค ~50๋ฐฐ ๋๋ฆฝ๋๋ค
- ๊ฐ์ฅ ๋๋ฆฐ ์ปค๋์ด ๊ฐ์ฅ ๋์ ์บ์ ํํธ์จ์ ๋ณด์ ๋๋ค (์์๊ณผ ์ ๋ฐ๋!)
- ์ผ๋ฐ์ ์ธ ์ฑ๋ฅ ์ง๊ด์ด ์์ ํ ๋น๋๊ฐ๋๋ค
ํ์ ์๋ฌด:
- ์ฑ๋ฅ ๋ฒ์ธ ์๋ณ - ์ด๋ค ์ปค๋์ด ์น๋ช ์ ์ผ๋ก ๋๋ฆฐ๊ฐ?
- ์บ์์ ์ญ์ค ๊ท๋ช - ๋์ ์บ์ ํํธ๊ฐ ์ ๋ฎ์ ์ฑ๋ฅ์ ์๋ฏธํ๋๊ฐ?
- ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ํด๋ - ๋์ผํ ์ฐ์ฐ์ด ์ด๋ป๊ฒ ์ด๋ ๊ฒ ๋ค๋ฅด๊ฒ ๋์ํ๋๊ฐ?
- ํ๋กํ์ผ๋ง ๋ฐฉ๋ฒ๋ก ํ์ต - ์ถ์ธก์ด ์๋ NSight ๋๊ตฌ๋ก ๊ทผ๊ฑฐ๋ฅผ ํ๋ณดํ๋ผ
์ ์ค์ํ๊ฐ: ์ด ํผ์ฆ์ CPU ๊ธฐ๋ฐ ์ง๊ด์ ๋์ ํ๋ GPU ์ฑ๋ฅ์ ๊ทผ๋ณธ ์๋ฆฌ๋ฅผ ๋๋ฌ๋ ๋๋ค. ์ฌ๊ธฐ์ ๊ธฐ๋ฅด๋ ์ญ๋์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ์๊ณ ๋ฆฌ์ฆ ๋ณต์ก๋๋ณด๋ค ์ค์ํ ์ค๋ฌด GPU ์ต์ ํ์ ์ง์ ์ ์ฉ๋ฉ๋๋ค.
๋ฐ์ : ์ด ๊ณผ์ ์ ํ๋ก๋์ ์ฑ๋ฅ ์ด์๋ฅผ ๋๋ฒ๊น ํ๋ฏ์ด, ์์ค ์ฝ๋๋ฅผ ๋จผ์ ๋ณด์ง ์๊ณ ํ๋กํ์ผ๋ง ๋๊ตฌ๋ง์ผ๋ก ์ ๊ทผํฉ๋๋ค. ํ๋กํ์ผ๋ง ๊ฒฐ๊ณผ๋ฅผ ์ป์ ํ์ ์ฝ๋๋ฅผ ๋ค์ฌ๋ค๋ด ๋๋ค.
ํ์ ๋๊ตฌ ๋ชจ์
ํ๋กํ์ผ๋ง ํํ ๋ฆฌ์ผ์์ ๋ฐฐ์ด ๋๊ตฌ๋ค:
- NSight Systems (
nsys) - ์ด๋ค ์ปค๋์ด ๋๋ฆฐ์ง ์ฐพ๊ธฐ - NSight Compute (
ncu) - ์ปค๋์ด ์ ๋๋ฆฐ์ง ๋ถ์ํ๊ธฐ - ๋ฉ๋ชจ๋ฆฌ ํจ์จ ์งํ - ๋นํจ์จ์ ์ธ ์ ๊ทผ ํจํด ํ์ง
์์ํ๊ธฐ
Step 1: ๋ฒค์น๋งํฌ ์คํ
pixi shell -e nvidia
mojo problems/p30/p30.mojo --benchmark
์ปค๋ ๊ฐ์ ๊ทน์ ์ธ ์คํ ์๊ฐ ์ฐจ์ด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค! ํ๋์ ์ปค๋์ด ๋๋จธ์ง๋ณด๋ค ํจ์ฌ ๋๋ฆฝ๋๋ค. ์ฝ๋๋ฅผ ๋ณด์ง ์๊ณ ํ๋กํ์ผ๋ง ๋๊ตฌ๋ง์ผ๋ก ์์ธ์ ์ฐพ์๋ด๋ ๊ฒ์ด ๋ชฉํ์ ๋๋ค.
์ถ๋ ฅ ์์:
| name | met (ms) | iters |
| ------- | --------- | ----- |
| kernel1 | 171.85 | 11 |
| kernel2 | 1546.68 | 11 | <- ์ด๊ฒ๋ง ์ ๋
๋๋ฆฌ๋ค!
| kernel3 | 172.18 | 11 |
Step 2: ํ๋กํ์ผ๋ง์ ์ํ ๋น๋ ์ค๋น
ํ์: ์ ํํ ํ๋กํ์ผ๋ง์ ์ํด ์ต์ ํ๋ฅผ ์ ์งํ๋ฉด์ ์ ์ฒด ๋๋ฒ๊ทธ ์ ๋ณด๋ฅผ ํฌํจํ์ฌ ๋น๋ํฉ๋๋ค:
mojo build --debug-level=full problems/p30/p30.mojo -o problems/p30/p30_profiler
์ค์ํ ์ด์ :
- ์ ์ฒด ๋๋ฒ๊ทธ ์ ๋ณด: ํ๋กํ์ผ๋ฌ์ ์์ ํ ์ฌ๋ณผ ํ ์ด๋ธ, ๋ณ์๋ช , ์์ค ๋ผ์ธ ๋งคํ์ ์ ๊ณต
- ์ข ํฉ ๋ถ์: NSight ๋๊ตฌ๊ฐ ์ฑ๋ฅ ๋ฐ์ดํฐ๋ฅผ ํน์ ์ฝ๋ ์์น์ ์ฐ๊ด ์ง๋ ๊ฒ์ด ๊ฐ๋ฅ
- ์ต์ ํ ์ ์ง: ํ๋ก๋์ ๋น๋์ ๋์ผํ ํ์ค์ ์ธ ์ฑ๋ฅ ์ธก์ ๋ณด์ฅ
Step 3: ์์คํ ์ ์ฒด ์กฐ์ฌ (NSight Systems)
๊ฐ ์ปค๋์ ํ๋กํ์ผ๋งํ์ฌ ์ ์ฒด ๊ทธ๋ฆผ์ ํ์ธํฉ๋๋ค:
# ์ต์ ํ ๋น๋๋ก ๊ฐ ์ปค๋์ ๊ฐ๋ณ ํ๋กํ์ผ๋ง (์ฝ๋ ์คํํธ ๋ฐฉ์ง๋ฅผ ์ํ ์๋ฐ์
ํฌํจ)
nsys profile --trace=cuda,osrt,nvtx --delay=2 --output=./problems/p30/kernel1_profile ./problems/p30/p30_profiler --kernel1
nsys profile --trace=cuda,osrt,nvtx --delay=2 --output=./problems/p30/kernel2_profile ./problems/p30/p30_profiler --kernel2
nsys profile --trace=cuda,osrt,nvtx --delay=2 --output=./problems/p30/kernel3_profile ./problems/p30/p30_profiler --kernel3
# ๊ฒฐ๊ณผ ๋ถ์
nsys stats --force-export=true ./problems/p30/kernel1_profile.nsys-rep > ./problems/p30/kernel1_profile.txt
nsys stats --force-export=true ./problems/p30/kernel2_profile.nsys-rep > ./problems/p30/kernel2_profile.txt
nsys stats --force-export=true ./problems/p30/kernel3_profile.nsys-rep > ./problems/p30/kernel3_profile.txt
ํ์ธํ ์ฌํญ:
- GPU ์ปค๋ ์์ฝ - ์ด๋ค ์ปค๋์ด ๊ฐ์ฅ ์ค๋ ๊ฑธ๋ฆฌ๋๊ฐ?
- ์ปค๋ ์คํ ์๊ฐ - ์ฐจ์ด๊ฐ ์ผ๋ง๋ ๋๋๊ฐ?
- ๋ฉ๋ชจ๋ฆฌ ์ ์ก ํจํด - ๊ตฌํ ๊ฐ์ ๋น์ทํ๊ฐ?
Step 4: ์ปค๋ ์ฌ์ธต ๋ถ์ (NSight Compute)
๋๋ฆฐ ์ปค๋์ ์๋ณํ ํ, NSight Compute๋ก ๋ถ์ํฉ๋๋ค:
# ์ต์ ํ ๋น๋๋ก ๊ฐ ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ํจํด ์ฌ์ธต ๋ถ์
ncu --set=@roofline --section=MemoryWorkloadAnalysis -f -o ./problems/p30/kernel1_analysis ./problems/p30/p30_profiler --kernel1
ncu --set=@roofline --section=MemoryWorkloadAnalysis -f -o ./problems/p30/kernel2_analysis ./problems/p30/p30_profiler --kernel2
ncu --set=@roofline --section=MemoryWorkloadAnalysis -f -o ./problems/p30/kernel3_analysis ./problems/p30/p30_profiler --kernel3
# ๊ฒฐ๊ณผ ํ์ธ
ncu --import ./problems/p30/kernel1_analysis.ncu-rep --page details
ncu --import ./problems/p30/kernel2_analysis.ncu-rep --page details
ncu --import ./problems/p30/kernel3_analysis.ncu-rep --page details
์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ถ๋ ฅ์ด ๋ํ๋ฉ๋๋ค:
Kernel1: Memory Throughput: ~308 Gbyte/s, Max Bandwidth: ~51%
Kernel2: Memory Throughput: ~6 Gbyte/s, Max Bandwidth: ~12%
Kernel3: Memory Throughput: ~310 Gbyte/s, Max Bandwidth: ~52%
์ฃผ์ ์กฐ์ฌ ์งํ:
- Memory Throughput (Gbyte/s) - ์ค์ ๋ฌ์ฑํ ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ
- Max Bandwidth (%) - ์ด๋ก ์ ์ต๋ ๋์ญํญ ๋๋น ํ์ฉ๋ฅ
- L1/TEX Hit Rate (%) - L1 ์บ์ ํจ์จ
- L2 Hit Rate (%) - L2 ์บ์ ํจ์จ
๐ค ๋ฐ์ง๊ด์ ์ธ ๊ฒฐ๊ณผ: Kernel2๊ฐ ๊ฐ์ฅ ๋์ ์บ์ ํํธ์จ์ ๋ณด์ด๋ฉด์ ๊ฐ์ฅ ๋ฎ์ ์ฑ๋ฅ์ ๋ณด์ ๋๋ค! ์ด๊ฒ์ด ํ์ด์ผ ํ ํต์ฌ ๋ฏธ์คํฐ๋ฆฌ์ ๋๋ค.
Step 5: ํ์ ์ง๋ฌธ
ํ๋กํ์ผ๋ง ๊ทผ๊ฑฐ๋ฅผ ๋ฐํ์ผ๋ก ์ปค๋ ์ฝ๋ problems/p30/p30.mojo๋ฅผ ์ดํด๋ณด๋ฉฐ ๋ค์ ์ง๋ฌธ์ ๋ตํด ๋ณด์ธ์:
์ฑ๋ฅ ๋ถ์
- ์ด๋ค ์ปค๋์ด ๊ฐ์ฅ ๋์ Memory Throughput์ ๋ฌ์ฑํ๋๊ฐ? (Gbyte/s ๊ฐ ํ์ธ)
- ์ด๋ค ์ปค๋์ Max Bandwidth ํ์ฉ๋ฅ ์ด ๊ฐ์ฅ ๋ฎ์๊ฐ? (๋ฐฑ๋ถ์จ ๋น๊ต)
- ๋ฉ๋ชจ๋ฆฌ ์ฒ๋ฆฌ๋์ ์ฑ๋ฅ ๊ฒฉ์ฐจ๋ ์ผ๋ง์ธ๊ฐ? (๊ฐ์ฅ ๋น ๋ฅธ ๊ฒ๊ณผ ๊ฐ์ฅ ๋๋ฆฐ ๊ฒ์ ๋ฐฐ์ ์ฐจ์ด)
์บ์์ ์ญ์ค
- ์ด๋ค ์ปค๋์ L1/TEX Hit Rate๊ฐ ๊ฐ์ฅ ๋์๊ฐ?
- ์ด๋ค ์ปค๋์ L2 Hit Rate๊ฐ ๊ฐ์ฅ ๋์๊ฐ?
- ๐คฏ ์บ์ ํํธ์จ์ด ๊ฐ์ฅ ๋์ ์ปค๋์ด ์ ์ฑ๋ฅ์ด ๊ฐ์ฅ ๋์๊ฐ?
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ํ๊ตฌ
- ๋์ ์บ์ ํํธ์จ์ด ์ค์ ๋ก ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋ํ๋ผ ์ ์๋๊ฐ?
- ์ด๋ค ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ๋์ ์บ์ ํํธ์ ๋ฎ์ ์ฒ๋ฆฌ๋์ ๋์์ ์ ๋ฐํ๋๊ฐ?
- ์ โํจ์จ์ ์ธ ์บ์ฑโ์ด โ๋นํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผโ์ ์ฆ์์ผ ์ ์๋๊ฐ?
โ์ํ!โ ์๊ฐ
- ํ๋กํ์ผ๋ง ๊ทผ๊ฑฐ๋ฅผ ๋ฐํ์ผ๋ก, ์ด ์ฌ๋ก๊ฐ ๋ณด์ฌ์ฃผ๋ GPU ๋ฉ๋ชจ๋ฆฌ์ ๊ทผ๋ณธ ์๋ฆฌ๋ ๋ฌด์์ธ๊ฐ?
๋ฐ๊ฒฌํ ํต์ฌ ํต์ฐฐ: ๋๋ก๋ ๋์ ์บ์ ํํธ์จ์ด ์ฑ๋ฅ ์น๋ฆฌ๊ฐ ์๋๋ผ ์ํ ์ ํธ์ ๋๋ค!
์๋ฃจ์
์ด ๋ฏธ์คํฐ๋ฆฌ๋ GPU ์ฑ๋ฅ์ ๊ทผ๋ณธ ์๋ฆฌ๋ฅผ ๋๋ฌ๋ ๋๋ค: ์ปค๋์ด ๋์ผํ ์ฐ์ฐ์ ์ํํ๋๋ผ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ฐ์ฐ์์๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ์ฑ๋ฅ์ ์ง๋ฐฐํฉ๋๋ค.
ํ๋กํ์ผ๋ง ๊ทผ๊ฑฐ๊ฐ ๋ฐํ๋ ๊ฒ:
- ์ฑ๋ฅ ์๊ณ: Kernel1๊ณผ Kernel3์ ๋น ๋ฅด๊ณ , Kernel2๋ ์น๋ช ์ ์ผ๋ก ๋๋ฆผ (์์ญ ๋ฐฐ ์ฐจ์ด)
- ๋ฉ๋ชจ๋ฆฌ ์ฒ๋ฆฌ๋์ด ๋ต์ ๋งํด์ค๋ค: ๋น ๋ฅธ ์ปค๋์ ๋์ ๋์ญํญ ํ์ฉ๋ฅ ์ ๋ฌ์ฑํ๊ณ , ๋๋ฆฐ ์ปค๋์ ์ต์ํ์ ํ์ฉ๋ฅ ๋ง ๋ฌ์ฑ
- ์บ์์ ์ญ์ค: ๊ฐ์ฅ ๋๋ฆฐ ์ปค๋์ด ๊ฐ์ฅ ๋์ ์บ์ ํํธ์จ์ ๋ณด์ - ๋์ ์บ์ ํํธ๊ฐ ๋นํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ๋ํ๋ผ ์ ์์์ ์์ฌ
- ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ GPU ์ํฌ๋ก๋์์๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ์๊ณ ๋ฆฌ์ฆ ๋ณต์ก๋๋ณด๋ค ์ค์
์์ธ ์๋ฃจ์ ๊ณผ ์ฌ์ธต ์ค๋ช
์ด ํ๋กํ์ผ๋ง ํ์ ์ฌ๊ฑด์ ์ปค๋์ด ๋์ผํ ์ํ ์ฐ์ฐ์ ์ํํ๋๋ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ์ด๋ป๊ฒ ์์ญ ๋ฐฐ์ ์ฑ๋ฅ ์ฐจ์ด๋ฅผ ๋ง๋ค์ด๋ด๋์ง ๋ณด์ฌ์ค๋๋ค.
ํ๋กํ์ผ๋ง์ผ๋ก ํ์ธํ ์ฑ๋ฅ ๊ทผ๊ฑฐ
NSight Systems ํ์๋ผ์ธ ๋ถ์:
- Kernel 1: ์งง์ ์คํ ์๊ฐ - ํจ์จ์
- Kernel 3: Kernel 1๊ณผ ์ ์ฌ - ํจ์จ์
- Kernel 2: ๊ทน์ ์ผ๋ก ๊ธด ์คํ ์๊ฐ - ๋นํจ์จ์
NSight Compute ๋ฉ๋ชจ๋ฆฌ ๋ถ์ (ํ๋์จ์ด ๋ฌด๊ดํ ํจํด):
- ํจ์จ์ ์ธ ์ปค๋ (1 & 3): ๋์ ๋ฉ๋ชจ๋ฆฌ ์ฒ๋ฆฌ๋, ์ํธํ ๋์ญํญ ํ์ฉ๋ฅ , ๋ณดํต ์์ค์ ์บ์ ํํธ์จ
- ๋นํจ์จ์ ์ธ ์ปค๋ (2): ๋งค์ฐ ๋ฎ์ ๋ฉ๋ชจ๋ฆฌ ์ฒ๋ฆฌ๋, ์ด์ ํ ๋์ญํญ ํ์ฉ๋ฅ , ๊ทน๋๋ก ๋์ ์บ์ ํํธ์จ
์บ์์ ์ญ์ค ๊ท๋ช
๐คฏ ๋ฐ์ง๊ด์ ์ธ ๋ฐ๊ฒฌ:
- Kernel2๊ฐ ๊ฐ์ฅ ๋์ ์บ์ ํํธ์จ์ ๋ณด์ด๋ฉด์ ์ฑ๋ฅ์ ์ต์
- ๊ธฐ์กด ์์์ ๋ํ ๋์ : โ๋์ ์บ์ ํํธ = ์ข์ ์ฑ๋ฅโ
- ์ง์ค: ๋์ ์บ์ ํํธ์จ์ ๋นํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ์ฆ์์ผ ์ ์์
์บ์์ ์ญ์ค์ด ๋ฐ์ํ๋ ์ด์ :
์ ํต์ ์ธ CPU ์ง๊ด (GPU์์๋ ํ๋ฆผ):
- ์บ์ ํํธ์จ์ด ๋์์๋ก ํญ์ ์ฑ๋ฅ์ด ์ข๋ค
- ์บ์ ํํธ๋ ๋ฉ๋ชจ๋ฆฌ ํธ๋ํฝ์ ์ค์ฌ ํจ์จ์ ๋์ธ๋ค
GPU ๋ฉ๋ชจ๋ฆฌ์ ํ์ค (์ฌ๋ฐ๋ฅธ ์ดํด):
- ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ํฌ๋ก๋์์๋ ๋ณํฉ์ด ์บ์ฑ๋ณด๋ค ์ค์
- ๋นํจ์จ์ ์ธ ์ ๊ทผ ํจํด์ ์ธ์์ ์ผ๋ก ์บ์ ํํธ์จ์ ๋ถํ๋ฆด ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ ํ์ฉ๋ฅ ์ด ์ง์ ํ ์ฑ๋ฅ ์งํ
๊ทผ๋ณธ ์์ธ ๋ถ์ - ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด
p30.mojo์ ์ค์ ์ปค๋ ๊ตฌํ:
Kernel 1 - ํจ์จ์ ์ธ ๋ณํฉ ์ ๊ทผ:
fn kernel1[
layout: Layout
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
b: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: Int,
):
i = Int(block_dim.x * block_idx.x + thread_idx.x)
if i < size:
output[i] = a[i] + b[i]
ํ์ค ์ค๋ ๋ ์ธ๋ฑ์ฑ - ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผ
Kernel 2 - ๋นํจ์จ์ ์ธ ์คํธ๋ผ์ด๋ ์ ๊ทผ:
fn kernel2[
layout: Layout
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
b: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: Int,
):
tid = Int(block_idx.x * block_dim.x + thread_idx.x)
stride = 512
i = tid
while i < size:
output[i] = a[i] + b[i]
i += stride
ํฐ stride=512๋ก ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ๊ฐ๊ฒฉ ๋ฐ์ - ๋์ผํ ์ฐ์ฐ์ด์ง๋ง ํฉ์ด์ง ์ ๊ทผ
Kernel 3 - ํจ์จ์ ์ธ ์ญ์ ์ ๊ทผ:
fn kernel3[
layout: Layout
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
b: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: Int,
):
tid = Int(block_idx.x * block_dim.x + thread_idx.x)
total_threads = (SIZE // 1024) * 1024
for step in range(0, size, total_threads):
forward_i = step + tid
if forward_i < size:
reverse_i = size - 1 - forward_i
output[reverse_i] = a[reverse_i] + b[reverse_i]
์ญ์ ์ธ๋ฑ์ฑ์ด์ง๋ง ์ฌ์ ํ ์์ธก ๊ฐ๋ฅ - ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ์ฃผ์์ ์ ๊ทผ (๋ฐฉํฅ๋ง ๋ฐ๋)
ํจํด ๋ถ์:
- Kernel 1: ์ ํ์ ์ธ ๋ณํฉ ์ ๊ทผ - ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผ
- Kernel 2: ์น๋ช ์ ์ธ ์คํธ๋ผ์ด๋ ์ ๊ทผ - ์ค๋ ๋๊ฐ 512๊ฐ ์์์ฉ ๊ฑด๋๋
- Kernel 3: ์ญ์์ด์ง๋ง ์ํ ๋ด์์๋ ๋ณํฉ ์ ์ง - ์์ธก ๊ฐ๋ฅํ ํจํด
๋ฉ๋ชจ๋ฆฌ ์์คํ ์ดํด
GPU ๋ฉ๋ชจ๋ฆฌ ์ํคํ ์ฒ ๊ธฐ์ด:
- ์ํ ์คํ: 32๊ฐ ์ค๋ ๋๊ฐ ํจ๊ป ์คํ
- ์บ์ ๋ผ์ธ ํฌ๊ธฐ: 128๋ฐ์ดํธ (float32 ๊ฐ 32๊ฐ)
- ๋ณํฉ ์๊ฑด: ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํด์ผ ํจ
p30.mojo ์ค์ ์์ธ:
comptime SIZE = 16 * 1024 * 1024 # 16M ์์ (float32 ๋ฐ์ดํฐ 64MB)
comptime THREADS_PER_BLOCK = (1024, 1) # ๋ธ๋ก๋น 1024 ์ค๋ ๋
comptime BLOCKS_PER_GRID = (SIZE // 1024, 1) # ์ด 16,384 ๋ธ๋ก
comptime dtype = DType.float32 # ์์๋น 4๋ฐ์ดํธ
์ด ์ค์ ์ด ์ค์ํ ์ด์ :
- ๋์ฉ๋ ๋ฐ์ดํฐ์ (16M): ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ์ฐจ์ด๊ฐ ๋ช ํํ๊ฒ ๋๋ฌ๋จ
- ๋ธ๋ก๋น 1024 ์ค๋ ๋: CUDA ์ต๋ ์ค๋ ๋ ์
- ๋ธ๋ก๋น 32๊ฐ ์ํ: ๊ฐ ๋ธ๋ก์ 32๊ฐ์ ์ํ(๊ฐ 32 ์ค๋ ๋)๊ฐ ํฌํจ
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจ์จ ์๊ฐํ:
KERNEL 1 (๋ณํฉ): KERNEL 2 (stride 512):
์ํ ์ค๋ ๋ 0-31: ์ํ ์ค๋ ๋ 0-31:
Thread 0: Memory[0] Thread 0: Memory[0]
Thread 1: Memory[1] Thread 1: Memory[512]
Thread 2: Memory[2] Thread 2: Memory[1024]
... ...
Thread 31: Memory[31] Thread 31: Memory[15872]
๊ฒฐ๊ณผ: ์บ์ ๋ผ์ธ 1ํ fetch ๊ฒฐ๊ณผ: ๋ณ๋์ ์บ์ ๋ผ์ธ 32ํ fetch
์ํ: ~308 GB/s ์ฒ๋ฆฌ๋ ์ํ: ~6 GB/s ์ฒ๋ฆฌ๋
์บ์: ํจ์จ์ ํ์ฉ ์บ์: ๊ฐ์ ๋ผ์ธ์ ๋ฐ๋ณต ํํธ!
KERNEL 3 (์ญ์์ด์ง๋ง ๋ณํฉ):
์ํ ์ค๋ ๋ 0-31 (์ฒซ ๋ฒ์งธ ๋ฐ๋ณต):
Thread 0: Memory[SIZE-1] (reverse_i = SIZE-1-0)
Thread 1: Memory[SIZE-2] (reverse_i = SIZE-1-1)
Thread 2: Memory[SIZE-3] (reverse_i = SIZE-1-2)
...
Thread 31: Memory[SIZE-32] (reverse_i = SIZE-1-31)
๊ฒฐ๊ณผ: ์ธ์ ํ ์ฃผ์ (๋ฐฉํฅ๋ง ๋ฐ๋)
์ํ: ~310 GB/s ์ฒ๋ฆฌ๋ (Kernel 1๊ณผ ๊ฑฐ์ ๋์ผ)
์บ์: ์ญ์์์๋ ํจ์จ์ ํ์ฉ
์บ์์ ์ญ์ค ์ค๋ช
Kernel2 (stride=512)๊ฐ ๋์ ์บ์ ํํธ์จ์๋ ์ฑ๋ฅ์ด ๋์ ์ด์ :
stride=512์ ์ฌ์ ์ค๋ช :
# ๊ฐ ์ค๋ ๋๊ฐ ํฐ ๊ฐ๊ฒฉ์ผ๋ก ์ฌ๋ฌ ์์๋ฅผ ์ฒ๋ฆฌ:
Thread 0: elements [0, 512, 1024, 1536, 2048, ...]
Thread 1: elements [1, 513, 1025, 1537, 2049, ...]
Thread 2: elements [2, 514, 1026, 1538, 2050, ...]
...
์ด๊ฒ์ด ์บ์์ ์ญ์ค์ ๋ง๋๋ ์ด์ :
- ์บ์ ๋ผ์ธ ๋ฐ๋ณต: 512๊ฐ ์์๋ฅผ ๊ฑด๋๋ฐ์ด๋ ๊ฒน์น๋ ์บ์ ๋ผ์ธ ์์ญ ์์ ๋จธ๋ฌด๋ฆ
- ๊ฑฐ์ง ํจ์จ์ ํ์: ๊ฐ์ ์บ์ ๋ผ์ธ์ ๋ฐ๋ณต ์ ๊ทผ = ์ธ์์ ์ผ๋ก ๋์ โํํธ์จโ
- ๋์ญํญ ์ฌ์: 32๊ฐ ์ค๋ ๋ ร 32๊ฐ ๋ณ๋ ์บ์ ๋ผ์ธ = ๋ง๋ํ ๋ฉ๋ชจ๋ฆฌ ํธ๋ํฝ
- ์ํ ์คํ ๋ถ์ผ์น: GPU๋ ๋ณํฉ ์ ๊ทผ์ ๋ง๊ฒ ์ค๊ณ๋์์ง๋ง, ํฉ์ด์ง ์ ๊ทผ์ ๋ฐ์
float32 (๊ฐ 4๋ฐ์ดํธ) ๊ตฌ์ฒด ์์:
- ์บ์ ๋ผ์ธ: 128๋ฐ์ดํธ = float32 ๊ฐ 32๊ฐ
- stride 512: ์ค๋ ๋๊ฐ 512ร4 = 2048๋ฐ์ดํธ = 16 ์บ์ ๋ผ์ธ ๊ฐ๊ฒฉ์ผ๋ก ์ ํ!
- ์ํ ์ํฅ: 32๊ฐ ์ค๋ ๋๊ฐ 1๊ฐ ๋์ 32๊ฐ์ ์๋ก ๋ค๋ฅธ ์บ์ ๋ผ์ธ์ ํ์๋ก ํจ
ํต์ฌ ํต์ฐฐ: Kernel2์ ๋์ ์บ์ ํํธ๋ ๋นํจ์จ์ ์ผ๋ก ๊ฐ์ ธ์จ ๋ฐ์ดํฐ์ ๋ํ ๋ฐ๋ณต ์ ๊ทผ์ด์ง, ํ๋ช ํ ์บ์ฑ์ด ์๋๋๋ค!
ํ๋กํ์ผ๋ง ๋ฐฉ๋ฒ๋ก ํต์ฐฐ
์ฒด๊ณ์ ํ์ ์ ๊ทผ๋ฒ:
1๋จ๊ณ: NSight Systems (์ ์ฒด ๊ทธ๋ฆผ)
- ์ด๋ค ์ปค๋์ด ๋๋ฆฐ์ง ์๋ณ
- ๋ช ๋ฐฑํ ๋ณ๋ชฉ ๋ฐฐ์ (๋ฉ๋ชจ๋ฆฌ ์ ์ก, API ์ค๋ฒํค๋)
- ์ปค๋ ์คํ ์๊ฐ ์ฐจ์ด์ ์ง์ค
2๋จ๊ณ: NSight Compute (์ฌ์ธต ๋ถ์)
- ๋ฉ๋ชจ๋ฆฌ ์ฒ๋ฆฌ๋ ์งํ ๋ถ์
- ๋์ญํญ ํ์ฉ๋ฅ ๋ฐฑ๋ถ์จ ๋น๊ต
- ์บ์ ํํธ์จ๊ณผ ํจํด ์กฐ์ฌ
3๋จ๊ณ: ๊ทผ๊ฑฐ๋ฅผ ์ด๋ก ์ผ๋ก ์ฐ๊ฒฐ
ํ๋กํ์ผ๋ง ๊ทผ๊ฑฐ โ ์ฝ๋ ๋ถ์:
NSight Compute ๊ฒฐ๊ณผ: ์ค์ ์ฝ๋ ํจํด:
- Kernel1: ~308 GB/s โ i = block_idx*block_dim + thread_idx (๋ณํฉ)
- Kernel2: ~6 GB/s, 99% L2 hits โ i += 512 (์น๋ช
์ stride)
- Kernel3: ~310 GB/s โ reverse_i = size-1-forward_i (์ญ์ ๋ณํฉ)
ํ๋กํ์ผ๋ฌ ๋ฐ์ดํฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจ์จ์ ์ง์ ๋๋ฌ๋
๋๋ค!
๊ทผ๊ฑฐ์์ ์ฝ๋๋ก์ ์ฐ๊ฒฐ:
- ๋์ ์ฒ๋ฆฌ๋ + ๋ณดํต ์บ์ ํํธ์จ = ๋ณํฉ ์ ๊ทผ (Kernel 1 & 3)
- ๋ฎ์ ์ฒ๋ฆฌ๋ + ๋์ ์บ์ ํํธ์จ = ๋นํจ์จ์ ์คํธ๋ผ์ด๋ ์ ๊ทผ (Kernel 2)
- ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ ํ์ฉ๋ฅ ์ด ์บ์ ํต๊ณ์ ๋ฌด๊ดํ๊ฒ ์ง์ ํ ํจ์จ์ ๋๋ฌ๋
์ค๋ฌด ์ฑ๋ฅ ์์ฌ์
์ด ํจํด์ด ์ํฅ์ ๋ฏธ์น๋ GPU ์์ฉ ๋ถ์ผ:
๊ณผํ ์ปดํจํ :
- ์คํ ์ค ์ฐ์ฐ: ๊ทธ๋ฆฌ๋ ์๋ฎฌ๋ ์ด์ ์์์ ์ด์ ์ ๊ทผ ํจํด
- ์ ํ ๋์: ํ๋ ฌ ์ํ ์์ (ํ ์ฐ์ vs ์ด ์ฐ์ )
- ํธ๋ฏธ๋ถ ๋ฐฉ์ ์ ํ์ด: ์ ํ ์ฐจ๋ถ๋ฒ์์์ ๊ฒฉ์์ ์ ๊ทผ ํจํด
๊ทธ๋ํฝ์ค ๋ฐ ์ด๋ฏธ์ง ์ฒ๋ฆฌ:
- ํ ์ค์ฒ ํํฐ๋ง: ์ ฐ์ด๋์์์ ์ํ ์ ๊ทผ ํจํด
- ์ด๋ฏธ์ง ํฉ์ฑ๊ณฑ: ํํฐ ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ
- ์ ๊ณต๊ฐ ๋ณํ: ์ฑ๋ ์ธํฐ๋ฆฌ๋น ์ ๋ต
๋จธ์ ๋ฌ๋:
- ํ๋ ฌ ์ฐ์ฐ: GEMM์์์ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ ์ต์ ํ
- ํ ์ ์ถ์ฝ: ๋ค์ฐจ์ ๋ฐฐ์ด ์ ๊ทผ ํจํด
- ๋ฐ์ดํฐ ๋ก๋ฉ: ๋ฐฐ์น ์ฒ๋ฆฌ์ ์ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ
GPU ์ต์ ํ์ ๊ทผ๋ณธ ์์น
๋ฉ๋ชจ๋ฆฌ ์ฐ์ ์ต์ ํ ์ ๋ต:
- ๋ฉ๋ชจ๋ฆฌ ํจํด์ด ์ง๋ฐฐ: ์ ๊ทผ ํจํด์ด ์๊ณ ๋ฆฌ์ฆ ๋ณต์ก๋๋ณด๋ค ๋ ์ค์ํ ๊ฒฝ์ฐ๊ฐ ๋ง์
- ๋ณํฉ์ด ํต์ฌ: ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋๋ก ์ค๊ณ
- ๋์ญํญ ํ์ฉ๋ฅ ์ธก์ : ์บ์ ํต๊ณ๊ฐ ์๋ ์ค์ ์ฒ๋ฆฌ๋์ ์ง์ค
- ์ฒด๊ณ์ ํ๋กํ์ผ๋ง: NSight ๋๊ตฌ๋ก ์ค์ ๋ณ๋ชฉ์ ํ์
ํต์ฌ ๊ธฐ์ ํต์ฐฐ:
- ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ํฌ๋ก๋: ๋์ญํญ ํ์ฉ๋ฅ ์ด ์ฑ๋ฅ์ ๊ฒฐ์
- ์บ์ ์งํ์ ํจ์ : ๋์ ํํธ์จ์ด ํญ์ ํจ์จ์ ์๋ฏธํ์ง๋ ์์
- ์ํ ๋ ๋ฒจ ์ฌ๊ณ : 32๊ฐ ์ค๋ ๋ ์คํ ๊ทธ๋ฃน์ ์ํ ์ ๊ทผ ํจํด ์ค๊ณ
- ํ๋์จ์ด ์ธ์ ํ๋ก๊ทธ๋๋ฐ: GPU ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ ์ดํด๊ฐ ํ์
ํต์ฌ ๊ตํ
์ด๋ฒ์ ํ๊ตฌํ ์ฌ๋ก๋ GPU ์ฑ๋ฅ ์ต์ ํ๊ฐ CPU ์ง๊ด์ ๋ฒ๋ฆฌ๊ณ ๋ฉ๋ชจ๋ฆฌ ์ค์ฌ ์ฌ๊ณ ๋ก ์ ํํ ๊ฒ์ ์๊ตฌํ๋ค๋ ์ ์ ๋ณด์ฌ์ค๋๋ค:
ํต์ฌ ํต์ฐฐ:
- ๋์ ์บ์ ํํธ์จ์ ์ข์ ์ฑ๋ฅ์ด ์๋๋ผ ๋นํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ๋ํ๋ผ ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ ํ์ฉ๋ฅ ์ด ์บ์ ํต๊ณ๋ณด๋ค ์ค์
- ๋จ์ํ ๋ณํฉ ํจํด์ด ๋ณต์กํ ์๊ณ ๋ฆฌ์ฆ๋ณด๋ค ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ๊ฐ ๋ง์
- ํ๋กํ์ผ๋ง ๋๊ตฌ๊ฐ ์ง๊ด์ผ๋ก๋ ์ ์ ์๋ ์ฑ๋ฅ์ ์ง์ค์ ๋๋ฌ๋
์ค์ ๋ฐฉ๋ฒ๋ก :
- NSight Systems์ NSight Compute๋ก ์ฒด๊ณ์ ์ผ๋ก ํ๋กํ์ผ๋ง
- ์ธ์ ์ค๋ ๋๊ฐ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋๋ก ์ค๊ณ (๋ณํฉ)
- ์ง๊ด์ด ์๋ ํ๋กํ์ผ๋ฌ ๊ทผ๊ฑฐ๋ฅผ ๋ฐํ์ผ๋ก ์ต์ ํ ๊ฒฐ์
์บ์์ ์ญ์ค์ ์ํคํ ์ฒ์ ๋ํ ์ดํด ์์ด ๊ณ ์์ค ์งํ์ ์์กดํ๋ฉด ์๋ชป๋ ๊ฒฐ๋ก ์ ์ด๋ฅผ ์ ์๋ค๋ ์ ์ ๋ณด์ฌ์ค๋๋ค - GPU ํ๋ก๊ทธ๋๋ฐ์ ๋์ด ๋๋ฃจ ์ ์ฉ๋๋ ๊ตํ์ ๋๋ค.