๐ Mojo GPU ๋๋ฒ๊น ์ ํต์ฌ
GPU ๋๋ฒ๊น ์ ์ธ๊ณ์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค! Puzzle 1-8์ ํตํด GPU ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ๋ฐฐ์ ์ผ๋, ์ด์ ๋ชจ๋ GPU ํ๋ก๊ทธ๋๋จธ์๊ฒ ๊ฐ์ฅ ์ค์ํ ๊ธฐ์ ์ ๋ฐฐ์ธ ์ค๋น๊ฐ ๋์์ต๋๋ค: ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ.
GPU ๋๋ฒ๊น ์ ์ฒ์์๋ ์ด๋ ค์ ๋ณด์ผ ์ ์์ต๋๋ค. ์์ฒ ๊ฐ์ ์ค๋ ๋๊ฐ ๋ณ๋ ฌ๋ก ์คํ๋๊ณ , ๋ค์ํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ด ์์ผ๋ฉฐ, ํ๋์จ์ด๋ณ ๋์๋ ๋ค๋ฃจ์ด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ ์ ํ ๋๊ตฌ์ ์ํฌํ๋ก์ฐ๋ง ์์ผ๋ฉด GPU ์ฝ๋ ๋๋ฒ๊น ๋ ์ฒด๊ณ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ CPU ํธ์คํธ ์ฝ๋(GPU ์์ ์ ์ค์ ํ๋ ๋ถ๋ถ)์ GPU ์ปค๋ ์ฝ๋(๋ณ๋ ฌ ์ฐ์ฐ์ด ์คํ๋๋ ๋ถ๋ถ) ๋ชจ๋๋ฅผ ๋๋ฒ๊น ํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค. ์ค์ ์์ , ์ค์ ๋๋ฒ๊ฑฐ ์ถ๋ ฅ, ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ๋ฐ๋ก ์ ์ฉํ ์ ์๋ ๋จ๊ณ๋ณ ์ํฌํ๋ก์ฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฐธ๊ณ : ๋ค์ ๋ด์ฉ์ ๋ฒ์ฉ IDE ํธํ์ฑ์ ์ํด ๋ช ๋ น์ค ๋๋ฒ๊น ์ ์ด์ ์ ๋ง์ถฅ๋๋ค. VS Code ๋๋ฒ๊น ์ ์ ํธํ๋ค๋ฉด Mojo ๋๋ฒ๊น ๋ฌธ์์์ VS Code ์ ์ฉ ์ค์ ๊ณผ ์ํฌํ๋ก์ฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
GPU ๋๋ฒ๊น ์ด ๋ค๋ฅธ ์ด์
๋๊ตฌ๋ก ๋ค์ด๊ฐ๊ธฐ ์ ์, GPU ๋๋ฒ๊น ์ด ํน๋ณํ ์ด์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
- ์ ํต์ ์ธ CPU ๋๋ฒ๊น : ๋จ์ผ ์ค๋ ๋, ์์ฐจ ์คํ, ๋จ์ํ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ
- GPU ๋๋ฒ๊น : ์์ฒ ๊ฐ์ ์ค๋ ๋, ๋ณ๋ ฌ ์คํ, ์ฌ๋ฌ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ, ๊ฒฝ์ ์ํ
์ด๋ ๋ค์์ ํ ์ ์๋ ์ ๋ฌธ ๋๊ตฌ๊ฐ ํ์ํ๋ค๋ ์๋ฏธ์ ๋๋ค:
- ์๋ก ๋ค๋ฅธ GPU ์ค๋ ๋ ๊ฐ ์ ํ
- ์ค๋ ๋๋ณ ๋ณ์์ ๋ฉ๋ชจ๋ฆฌ ๊ฒ์ฌ
- ๋ณ๋ ฌ ์คํ์ ๋ณต์ก์ฑ ์ฒ๋ฆฌ
- CPU ์ค์ ์ฝ๋์ GPU ์ปค๋ ์ฝ๋ ๋ชจ๋ ๋๋ฒ๊น
๋๋ฒ๊น ๋๊ตฌ ๋ชจ์
Mojo์ GPU ๋๋ฒ๊น ๊ธฐ๋ฅ์ ํ์ฌ NVIDIA GPU๋ก ์ ํ๋ฉ๋๋ค. Mojo ๋๋ฒ๊น ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด Mojo ํจํค์ง์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค:
- CPU ์ธก ๋๋ฒ๊น ์ ์ํ Mojo ํ๋ฌ๊ทธ์ธ์ด ํฌํจ๋ LLDB ๋๋ฒ๊ฑฐ
- GPU ์ปค๋ ๋๋ฒ๊น ์ ์ํ CUDA-GDB ํตํฉ
- ๋ฒ์ฉ IDE ํธํ์ฑ์ ์ํ
mojo debug๋ฅผ ํตํ ๋ช ๋ น์ค ์ธํฐํ์ด์ค
GPU ์ ์ฉ ๋๋ฒ๊น ์ ๋ํด์๋ Mojo GPU ๋๋ฒ๊น ๊ฐ์ด๋์์ ์ถ๊ฐ ๊ธฐ์ ์ธ๋ถ ์ฌํญ์ ์ ๊ณตํฉ๋๋ค.
์ด ์ํคํ ์ฒ๋ ์ต์ํ ๋๋ฒ๊น ๋ช ๋ น์ด์ GPU ์ ์ฉ ๊ธฐ๋ฅ, ๋ ๊ฐ์ง ์ฅ์ ์ ๋ชจ๋ ์ ๊ณตํฉ๋๋ค.
๋๋ฒ๊น ์ํฌํ๋ก์ฐ: ๋ฌธ์ ์์ ํด๊ฒฐ๊น์ง
GPU ํ๋ก๊ทธ๋จ์ด ํฌ๋์ํ๊ฑฐ๋, ์๋ชป๋ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ฑฐ๋, ์์์น ๋ชปํ ๋์์ ํ ๋ ๋ค์์ ์ฒด๊ณ์ ์ธ ์ ๊ทผ๋ฒ์ ๋ฐ๋ฅด์ธ์:
- ๋๋ฒ๊น ์ ์ํ ์ฝ๋ ์ค๋น (์ต์ ํ ๋นํ์ฑํ, ๋๋ฒ๊ทธ ์ฌ๋ณผ ์ถ๊ฐ)
- ์ ์ ํ ๋๋ฒ๊ฑฐ ์ ํ (CPU ํธ์คํธ ์ฝ๋ vs GPU ์ปค๋ ๋๋ฒ๊น )
- ์ ๋ต์ ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์ (๋ฌธ์ ๊ฐ ์์ฌ๋๋ ์์น์)
- ์คํ ๋ฐ ๊ฒ์ฌ (์ฝ๋๋ฅผ ๋จ๊ณ๋ณ๋ก ์คํํ๋ฉฐ ๋ณ์ ๊ฒ์ฌ)
- ํจํด ๋ถ์ (๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ, ์ค๋ ๋ ๋์, ๊ฒฝ์ ์ํ)
์ด ์ํฌํ๋ก์ฐ๋ Puzzle 01์ ๊ฐ๋จํ ๋ฐฐ์ด ์ฐ์ฐ์ด๋ Puzzle 08์ ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฝ๋๋ ์๊ด์์ด ์๋ํฉ๋๋ค.
Step 1: ๋๋ฒ๊น ์ ์ํ ์ฝ๋ ์ค๋น
๐ฅ ์ฒ ์น: ์ต์ ํ๋ ์ฝ๋๋ ์ ๋ ๋๋ฒ๊น ํ์ง ๋ง์ธ์. ์ต์ ํ๋ ๋ช ๋ น์ด ์์๋ฅผ ๋ฐ๊พธ๊ณ , ๋ณ์๋ฅผ ์ ๊ฑฐํ๊ณ , ํจ์๋ฅผ ์ธ๋ผ์ธํํ์ฌ ๋๋ฒ๊น ์ ๊ฑฐ์ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค.
๋๋ฒ๊ทธ ์ ๋ณด๋ก ๋น๋ํ๊ธฐ
๋๋ฒ๊น ์ฉ Mojo ํ๋ก๊ทธ๋จ์ ๋น๋ํ ๋๋ ํญ์ ๋๋ฒ๊ทธ ์ฌ๋ณผ์ ํฌํจํ์ธ์:
# ์ ์ฒด ๋๋ฒ๊ทธ ์ ๋ณด๋ก ๋น๋
mojo build -O0 -g your_program.mojo -o your_program_debug
์ด ํ๋๊ทธ๋ค์ด ํ๋ ์ผ:
-O0: ๋ชจ๋ ์ต์ ํ๋ฅผ ๋นํ์ฑํํ์ฌ ์๋ ์ฝ๋ ๊ตฌ์กฐ๋ฅผ ๋ณด์กด-g: ๋๋ฒ๊ฑฐ๊ฐ ๋จธ์ ์ฝ๋๋ฅผ Mojo ์์ค์ ๋งคํํ ์ ์๋๋ก ๋๋ฒ๊ทธ ์ฌ๋ณผ ํฌํจ-o: ์ฌ์ด ์๋ณ์ ์ํด ๋ช ๋ช ๋ ์ถ๋ ฅ ํ์ผ ์์ฑ
์ด๊ฒ์ด ์ค์ํ ์ด์
๋๋ฒ๊ทธ ์ฌ๋ณผ ์์ด๋ ๋๋ฒ๊น ์ธ์ ์ด ์ด๋ ๊ฒ ๋ณด์ ๋๋ค:
(lldb) print my_variable
error: use of undeclared identifier 'my_variable'
๋๋ฒ๊ทธ ์ฌ๋ณผ์ด ์์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค:
(lldb) print my_variable
(int) $0 = 42
Step 2: ๋๋ฒ๊น ์ ๊ทผ๋ฒ ์ ํ
์ฌ๊ธฐ์ GPU ๋๋ฒ๊น ์ด ํฅ๋ฏธ๋ก์์ง๋๋ค. ๋ค ๊ฐ์ง ๋ค๋ฅธ ์กฐํฉ ์ค์์ ์ ํํ ์ ์์ผ๋ฉฐ, ์ ์ ํ ๊ฒ์ ๊ณ ๋ฅด๋ฉด ์๊ฐ์ ์ ์ฝํ ์ ์์ต๋๋ค:
๋ค ๊ฐ์ง ๋๋ฒ๊น ์กฐํฉ
๋น ๋ฅธ ์ฐธ์กฐ:
# 1. JIT + LLDB: ์์ค์์ ์ง์ CPU ํธ์คํธ ์ฝ๋ ๋๋ฒ๊น
pixi run mojo debug your_gpu_program.mojo
# 2. JIT + CUDA-GDB: ์์ค์์ ์ง์ GPU ์ปค๋ ๋๋ฒ๊น
pixi run mojo debug --cuda-gdb --break-on-launch your_gpu_program.mojo
# 3. ๋ฐ์ด๋๋ฆฌ + LLDB: ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ์์ CPU ํธ์คํธ ์ฝ๋ ๋๋ฒ๊น
pixi run mojo build -O0 -g your_gpu_program.mojo -o your_program_debug
pixi run mojo debug your_program_debug
# 4. ๋ฐ์ด๋๋ฆฌ + CUDA-GDB: ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ์์ GPU ์ปค๋ ๋๋ฒ๊น
pixi run mojo debug --cuda-gdb --break-on-launch your_program_debug
๊ฐ ์ ๊ทผ๋ฒ์ ์ธ์ ์ฌ์ฉํ ๊น
ํ์ต๊ณผ ๋น ๋ฅธ ์คํ์ฉ:
- JIT ๋๋ฒ๊น ์ฌ์ฉ - ๋น๋ ๋จ๊ณ๊ฐ ํ์ ์์ด ๋ ๋น ๋ฅด๊ฒ ๋ฐ๋ณต ๊ฐ๋ฅ
๋ณธ๊ฒฉ์ ์ธ ๋๋ฒ๊น ์ธ์ ์ฉ:
- ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น ์ฌ์ฉ - ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ๊น๋ํ ๋๋ฒ๊ฑฐ ์ถ๋ ฅ
CPU ์ธก ๋ฌธ์ ์ฉ (๋ฒํผ ํ ๋น, ํธ์คํธ ๋ฉ๋ชจ๋ฆฌ, ํ๋ก๊ทธ๋จ ๋ก์ง):
- LLDB ๋ชจ๋ ์ฌ์ฉ -
main()ํจ์์ ์ค์ ์ฝ๋ ๋๋ฒ๊น ์ ์ ํฉ
GPU ์ปค๋ ๋ฌธ์ ์ฉ (์ค๋ ๋ ๋์, GPU ๋ฉ๋ชจ๋ฆฌ, ์ปค๋ ํฌ๋์):
- CUDA-GDB ๋ชจ๋ ์ฌ์ฉ - ๊ฐ๋ณ GPU ์ค๋ ๋๋ฅผ ๊ฒ์ฌํ๋ ์ ์ผํ ๋ฐฉ๋ฒ
์ฅ์ ์ ๋ค์ํ๊ฒ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์๋ค๋ ์ ์ ๋๋ค. JIT + LLDB๋ก ์ค์ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ ๋ค์, JIT + CUDA-GDB๋ก ์ ํํด์ ์ค์ ์ปค๋์ ๋๋ฒ๊น ํ ์ ์์ต๋๋ค.
CUDA-GDB๋ก GPU ์ปค๋ ๋๋ฒ๊น ์ดํดํ๊ธฐ
์ด์ GPU ์ปค๋ ๋๋ฒ๊น ์ ๋๋ค - ๋๋ฒ๊น ๋๊ตฌ ๋ชจ์์์ ๊ฐ์ฅ ๊ฐ๋ ฅํ๋ฉด์๋ ๋ณต์กํ ๋ถ๋ถ์ ๋๋ค.
--cuda-gdb๋ฅผ ์ฌ์ฉํ๋ฉด Mojo๋ NVIDIA์ CUDA-GDB ๋๋ฒ๊ฑฐ์ ํตํฉ๋ฉ๋๋ค. ์ด๊ฒ์ ๋จ์ํ ๋๋ฒ๊ฑฐ๊ฐ ์๋๋๋ค - GPU ์ปดํจํ
์ ๋ณ๋ ฌ ๋ฉํฐ์ค๋ ๋ ์ธ๊ณ๋ฅผ ์ํด ํน๋ณํ ์ค๊ณ๋์์ต๋๋ค.
CUDA-GDB๊ฐ ํน๋ณํ ์ด์
์ผ๋ฐ GDB๋ ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ฅผ ๋๋ฒ๊น ํ๋ฉฐ ์์ฐจ ์ฝ๋๋ฅผ ๋จ๊ณ๋ณ๋ก ์คํํฉ๋๋ค. CUDA-GDB๋ ์์ฒ ๊ฐ์ GPU ์ค๋ ๋๋ฅผ ๋์์ ๋๋ฒ๊น ํ๋ฉฐ, ๊ฐ๊ฐ์ด ์๋ก ๋ค๋ฅธ ๋ช ๋ น์ด๋ฅผ ์คํํ ์ ์์ต๋๋ค.
์ด๋ ๋ค์์ ํ ์ ์๋ค๋ ์๋ฏธ์ ๋๋ค:
- GPU ์ปค๋ ๋ด๋ถ์ ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์ - ์ด๋ค ์ค๋ ๋๋ ๋ธ๋ ์ดํฌํฌ์ธํธ์ ๋๋ฌํ๋ฉด ์คํ์ ์ผ์ ์ ์ง
- GPU ์ค๋ ๋ ๊ฐ ์ ํ - ๊ฐ์ ์๊ฐ์ ์๋ก ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ฌด์์ ํ๋์ง ๊ฒ์ฌ
- ์ค๋ ๋๋ณ ๋ฐ์ดํฐ ๊ฒ์ฌ - ๊ฐ์ ๋ณ์๊ฐ ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง๋ ๊ฒ์ ํ์ธ
- ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ๋๋ฒ๊น - ๋ฒ์ ์ด๊ณผ ์ ๊ทผ, ๊ฒฝ์ ์ํ, ๋ฉ๋ชจ๋ฆฌ ์์ ํฌ์ฐฉ (์ด๋ฐ ๋ฌธ์ ๊ฐ์ง์ ๋ํด์๋ Puzzle 10์์ ๋ ์์ธํ)
- ๋ณ๋ ฌ ์คํ ๋ถ์ - ์ค๋ ๋๋ค์ด ์ด๋ป๊ฒ ์ํธ์์ฉํ๊ณ ๋๊ธฐํํ๋์ง ์ดํด
์ด์ ํผ์ฆ์ ๊ฐ๋ ๊ณผ ์ฐ๊ฒฐ
Puzzle 1-8์์ ๋ฐฐ์ด GPU ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ๊ธฐ์ตํ์๋์? CUDA-GDB๋ก ๋ฐํ์์ ๋ชจ๋ ๊ฒ์ ๊ฒ์ฌํ ์ ์์ต๋๋ค:
์ค๋ ๋ ๊ณ์ธต ๊ตฌ์กฐ ๋๋ฒ๊น
Puzzle 1-8์์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค:
# Puzzle 1์์: ๊ธฐ๋ณธ ์ค๋ ๋ ์ธ๋ฑ์ฑ
i = thread_idx.x # ๊ฐ ์ค๋ ๋๊ฐ ๊ณ ์ ํ ์ธ๋ฑ์ค๋ฅผ ์ป์
# Puzzle 7์์: 2D ์ค๋ ๋ ์ธ๋ฑ์ฑ
row = thread_idx.y # 2D ์ค๋ ๋ ๊ทธ๋ฆฌ๋
col = thread_idx.x
CUDA-GDB๋ก ์ด ์ค๋ ๋ ์ขํ๋ค์ด ์ค์ ๋ก ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค:
(cuda-gdb) info cuda threads
์ถ๋ ฅ:
BlockIdx ThreadIdx To BlockIdx To ThreadIdx Count PC Filename Line
Kernel 0
* (0,0,0) (0,0,0) (0,0,0) (3,0,0) 4 0x00007fffcf26fed0 /home/ubuntu/workspace/mojo-gpu-puzzles/solutions/p01/p01.mojo 13
๊ทธ๋ฆฌ๊ณ ํน์ ์ค๋ ๋๋ก ์ด๋ํด์ ๋ฌด์์ ํ๋์ง ๋ณผ ์ ์์ต๋๋ค:
(cuda-gdb) cuda thread (1,0,0)
์ถ๋ ฅ:
[Switching to CUDA thread (1,0,0)]
์ ๋ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋๋ค - ๋ง ๊ทธ๋๋ก ๋ณ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ด ์ฌ๋ฌ ์ค๋ ๋์์ ์คํ๋๋ ๊ฒ์ ์ง์ ์ง์ผ๋ณผ ์ ์์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ๋๋ฒ๊น
๋ค์ํ ์ ํ์ GPU ๋ฉ๋ชจ๋ฆฌ์ ๋ํด ๋ฐฐ์ด Puzzle 8์ ๊ธฐ์ตํ์๋์? CUDA-GDB๋ก ๋ชจ๋ ๊ฒ์ ๊ฒ์ฌํ ์ ์์ต๋๋ค:
# ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ๊ฒ์ฌ (Puzzle 1-5์ ๋ฐฐ์ด๋ค)
(cuda-gdb) print input_array[0]@4
$1 = {{1}, {2}, {3}, {4}} # Mojo ์ค์นผ๋ผ ํ์
# ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํด ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๊ฒ์ฌ (thread_idx.x๋ ์๋ํ์ง ์์)
(cuda-gdb) print shared_data[i] # thread_idx.x ๋์ ๋ก์ปฌ ๋ณ์ 'i' ์ฌ์ฉ
$2 = {42}
๋๋ฒ๊ฑฐ๋ ๊ฐ ์ค๋ ๋๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ์ ํํ ๋ฌด์์ ๋ณด๋์ง ๋ณด์ฌ์ค๋๋ค. ์ด๋ ๊ฒฝ์ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ๋ฒ๊ทธ๋ฅผ ์ก๊ธฐ์ ์๋ฒฝํฉ๋๋ค.
์ ๋ต์ ๋ธ๋ ์ดํฌํฌ์ธํธ ๋ฐฐ์น
CUDA-GDB ๋ธ๋ ์ดํฌํฌ์ธํธ๋ ๋ณ๋ ฌ ์คํ๊ณผ ํจ๊ป ์๋ํ๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ๋ธ๋ ์ดํฌํฌ์ธํธ๋ณด๋ค ํจ์ฌ ๊ฐ๋ ฅํฉ๋๋ค:
# ์ด๋ค ์ค๋ ๋๋ ์ปค๋์ ์ง์
ํ ๋ ์ค๋จ
(cuda-gdb) break add_kernel
# ํน์ ์ค๋ ๋์ ๋ํด์๋ง ์ค๋จ (๋ฌธ์ ๊ฒฉ๋ฆฌ์ ์ข์)
(cuda-gdb) break add_kernel if thread_idx.x == 0
# ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์๋ฐ ์ ์ค๋จ
(cuda-gdb) watch input_array[thread_idx.x]
# ํน์ ๋ฐ์ดํฐ ์กฐ๊ฑด์์ ์ค๋จ
(cuda-gdb) break add_kernel if input_array[thread_idx.x] > 100.0
์ด๋ฅผ ํตํด ์์ฒ ๊ฐ ์ค๋ ๋์ ์ถ๋ ฅ์ ํ๋ฌปํ์ง ์๊ณ ์ ํํ ๊ด์ฌ ์๋ ์ค๋ ๋์ ์กฐ๊ฑด์ ์ง์คํ ์ ์์ต๋๋ค.
ํ๊ฒฝ ์ค๋นํ๊ธฐ
๋๋ฒ๊น ์ ์์ํ๊ธฐ ์ ์ ๊ฐ๋ฐ ํ๊ฒฝ์ด ์ ๋๋ก ๊ตฌ์ฑ๋์ด ์๋์ง ํ์ธํ์ธ์. ์ด์ ํผ์ฆ๋ค์ ์งํํด์๋ค๋ฉด ๋๋ถ๋ถ ์ด๋ฏธ ์ค์ ๋์ด ์์ ๊ฒ์ ๋๋ค!
์ฐธ๊ณ : pixi ์์ด๋ NVIDIA ๊ณต์ ๋ฆฌ์์ค์์ CUDA Toolkit์ ์๋์ผ๋ก ์ค์นํ๊ณ , ๋๋ผ์ด๋ฒ ํธํ์ฑ์ ๊ด๋ฆฌํ๊ณ , ํ๊ฒฝ ๋ณ์๋ฅผ ๊ตฌ์ฑํ๊ณ , ์ปดํฌ๋ํธ ๊ฐ ๋ฒ์ ์ถฉ๋์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. pixi๋ ๋ชจ๋ CUDA ์์กด์ฑ, ๋ฒ์ , ํ๊ฒฝ ๊ตฌ์ฑ์ ์๋์ผ๋ก ๊ด๋ฆฌํ์ฌ ์ด ๋ณต์ก์ฑ์ ์ ๊ฑฐํฉ๋๋ค.
pixi๊ฐ ๋๋ฒ๊น
์ ์ค์ํ ์ด์
๋ฌธ์ ์ : GPU ๋๋ฒ๊น ์ CUDA ํดํท, GPU ๋๋ผ์ด๋ฒ, Mojo ์ปดํ์ผ๋ฌ, ๋๋ฒ๊ฑฐ ์ปดํฌ๋ํธ ๊ฐ์ ์ ๋ฐํ ์กฐ์จ์ด ํ์ํฉ๋๋ค. ๋ฒ์ ๋ถ์ผ์น๋ โ๋๋ฒ๊ฑฐ๋ฅผ ์ฐพ์ ์ ์์โ ์ค๋ฅ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
ํด๊ฒฐ์ฑ
: pixi๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ์กฐํ๋กญ๊ฒ ์๋ํฉ๋๋ค. pixi run mojo debug --cuda-gdb๋ฅผ ์คํํ๋ฉด pixi๊ฐ ์๋์ผ๋ก:
- CUDA ํดํท ๊ฒฝ๋ก ์ค์
- ์ฌ๋ฐ๋ฅธ GPU ๋๋ผ์ด๋ฒ ๋ก๋
- Mojo ๋๋ฒ๊น ํ๋ฌ๊ทธ์ธ ๊ตฌ์ฑ
- ํ๊ฒฝ ๋ณ์๋ฅผ ์ผ๊ด๋๊ฒ ๊ด๋ฆฌ
์ค์ ํ์ธ
๋ชจ๋ ๊ฒ์ด ์๋ํ๋์ง ํ์ธํด ๋ด ์๋ค:
# 1. GPU ํ๋์จ์ด ์ ๊ทผ ๊ฐ๋ฅ ์ฌ๋ถ ํ์ธ
pixi run nvidia-smi
# GPU์ ๋๋ผ์ด๋ฒ ๋ฒ์ ์ด ํ์๋์ด์ผ ํจ
# 2. CUDA-GDB ํตํฉ ์ค์ (GPU ๋๋ฒ๊น
์ ํ์)
pixi run setup-cuda-gdb
# ์์คํ
CUDA-GDB ๋ฐ์ด๋๋ฆฌ๋ฅผ conda ํ๊ฒฝ์ ๋งํฌ
# 3. Mojo ๋๋ฒ๊ฑฐ ์ฌ์ฉ ๊ฐ๋ฅ ์ฌ๋ถ ํ์ธ
pixi run mojo debug --help
# --cuda-gdb๋ฅผ ํฌํจํ ๋๋ฒ๊น
์ต์
์ด ํ์๋์ด์ผ ํจ
# 4. CUDA-GDB ํตํฉ ํ
์คํธ
pixi run cuda-gdb --version
# NVIDIA CUDA-GDB ๋ฒ์ ์ ๋ณด๊ฐ ํ์๋์ด์ผ ํจ
์ด ๋ช
๋ น์ด ์ค ํ๋๋ผ๋ ์คํจํ๋ฉด pixi.toml ๊ตฌ์ฑ์ ๋ค์ ํ์ธํ๊ณ CUDA ํดํท ๊ธฐ๋ฅ์ด ํ์ฑํ๋์ด ์๋์ง ํ์ธํ์ธ์.
์ค์: conda์ cuda-gdb ํจํค์ง๋ ๋ํผ ์คํฌ๋ฆฝํธ๋ง ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ pixi run setup-cuda-gdb ๋ช
๋ น์ด ํ์ํฉ๋๋ค. ์ด ๋ช
๋ น์ ์์คํ
CUDA ์ค์น์์ ์ค์ CUDA-GDB ๋ฐ์ด๋๋ฆฌ๋ฅผ ์๋ ๊ฐ์งํ๊ณ conda ํ๊ฒฝ์ ๋งํฌํ์ฌ ์ ์ฒด GPU ๋๋ฒ๊น
๊ธฐ๋ฅ์ ํ์ฑํํฉ๋๋ค.
์ด ๋ช ๋ น์ด ํ๋ ์ผ:
์คํฌ๋ฆฝํธ๋ ์ฌ๋ฌ ์ผ๋ฐ์ ์ธ ์์น์์ CUDA๋ฅผ ์๋ ๊ฐ์งํฉ๋๋ค:
$CUDA_HOMEํ๊ฒฝ ๋ณ์/usr/local/cuda(Ubuntu/Debian ๊ธฐ๋ณธ๊ฐ)/opt/cuda(ArchLinux ๋ฐ ๊ธฐํ ๋ฐฐํฌํ)- ์์คํ
PATH (
which cuda-gdbํตํด)
๊ตฌํ ์ธ๋ถ ์ฌํญ์ scripts/setup-cuda-gdb.sh๋ฅผ ์ฐธ์กฐํ์ธ์.
WSL ์ฌ์ฉ์๋ฅผ ์ํ ํน๋ณ ์ฐธ๊ณ ์ฌํญ: Part II์์ ์ฌ์ฉํ ๋ ๊ฐ์ง ๋๋ฒ๊ทธ ๋๊ตฌ(cuda-gdb์ compute-sanitizer)๋ WSL์์ CUDA ์ ํ๋ฆฌ์ผ์ด์
๋๋ฒ๊น
์ ์ง์ํ์ง๋ง, ๋ ์ง์คํธ๋ฆฌ ํค HKEY_LOCAL_MACHINE\SOFTWARE\NVIDIA Corporation\GPUDebugger\EnableInterface๋ฅผ ์ถ๊ฐํ๊ณ (DWORD) 1๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ์ง์๋๋ ํ๋ซํผ๊ณผ OS๋ณ ๋์์ ๋ํ ์์ธํ ๋ด์ฉ์ cuda-gdb์ compute-sanitizer๋ฅผ ์ฐธ์กฐํ์ธ์.
์ค์ต ํํ ๋ฆฌ์ผ: ์ฒซ GPU ๋๋ฒ๊น ์ธ์
์ด๋ก ๋ ์ข์ง๋ง ์ง์ ๊ฒฝํํ๋ ๊ฒ๋ง ํ ๊ฒ ์์ต๋๋ค. Puzzle 01 - ์ฌ๋ฌ๋ถ์ด ์ ์๋ ๊ฐ๋จํ โ๋ฐฐ์ด ๊ฐ ์์์ 10 ๋ํ๊ธฐโ ์ปค๋์ ์ฌ์ฉํด์ ์ค์ ํ๋ก๊ทธ๋จ์ ๋๋ฒ๊น ํด ๋ด ์๋ค.
์ Puzzle 01์ธ๊ฐ? ๋ค์ ์ด์ ๋ก ์๋ฒฝํ ๋๋ฒ๊น ํํ ๋ฆฌ์ผ์ ๋๋ค:
- ์ถฉ๋ถํ ๋จ์ํด์ ๋ฌด์์ด ์ผ์ด๋์ผ ํ๋์ง ์ดํดํ ์ ์์
- ์ค์ ์ปค๋ ์คํ์ด ์๋ ์ง์ง GPU ์ฝ๋
- CPU ์ค์ ์ฝ๋์ GPU ์ปค๋ ์ฝ๋ ๋ชจ๋ ํฌํจ
- ์งง์ ์คํ ์๊ฐ์ผ๋ก ๋น ๋ฅธ ๋ฐ๋ณต ๊ฐ๋ฅ
์ด ํํ ๋ฆฌ์ผ์ด ๋๋๋ฉด ๋ค ๊ฐ์ง ๋๋ฒ๊น ์ ๊ทผ๋ฒ ๋ชจ๋๋ก ๊ฐ์ ํ๋ก๊ทธ๋จ์ ๋๋ฒ๊น ํ๊ณ , ์ค์ ๋๋ฒ๊ฑฐ ์ถ๋ ฅ์ ๋ณด๊ณ , ๋งค์ผ ์ฌ์ฉํ ํ์ ๋๋ฒ๊น ๋ช ๋ น์ด๋ฅผ ๋ฐฐ์ฐ๊ฒ ๋ฉ๋๋ค.
๋๋ฒ๊น ์ ๊ทผ๋ฒ ํ์ต ๊ฒฝ๋ก
Puzzle 01์ ์์ ๋ก ๋ค ๊ฐ์ง ๋๋ฒ๊น ์กฐํฉ์ ํ์ํฉ๋๋ค. ํ์ต ๊ฒฝ๋ก: JIT + LLDB(๊ฐ์ฅ ์ฌ์)๋ก ์์ํด์ CUDA-GDB(๊ฐ์ฅ ๊ฐ๋ ฅํจ)๋ก ์งํํฉ๋๋ค.
โ ๏ธ GPU ๋๋ฒ๊น ์ ์ค์์ฌํญ:
--break-on-launchํ๋๊ทธ๋ CUDA-GDB ์ ๊ทผ๋ฒ์์ ํ์- ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ (์ ๊ทผ๋ฒ 3 & 4)๋ ๋๋ฒ๊น
์ ์ํด
i๊ฐ์ ๋ก์ปฌ ๋ณ์๋ฅผ ๋ณด์กด - JIT ์ปดํ์ผ (์ ๊ทผ๋ฒ 1 & 2)์ ๋๋ถ๋ถ์ ๋ก์ปฌ ๋ณ์๋ฅผ ์ต์ ํ๋ก ์ ๊ฑฐ
- ๋ณธ๊ฒฉ์ ์ธ GPU ๋๋ฒ๊น ์๋ ์ ๊ทผ๋ฒ 4 (๋ฐ์ด๋๋ฆฌ + CUDA-GDB) ์ฌ์ฉ
ํํ ๋ฆฌ์ผ Step 1: LLDB๋ก CPU ๋๋ฒ๊น
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋๋ฒ๊น
์๋๋ฆฌ์ค๋ก ์์ํฉ์๋ค: ํ๋ก๊ทธ๋จ์ด ํฌ๋์ํ๊ฑฐ๋ ์์์น ๋ชปํ ๋์์ ํด์ main() ํจ์์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ๋ด์ผ ํ ๋.
๋ฏธ์ : Puzzle 01์ CPU ์ธก ์ค์ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ์ฌ Mojo๊ฐ GPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ด๊ธฐํํ๊ณ ์ปค๋์ ์คํํ๋ ๋ฐฉ๋ฒ์ ํ์ ํฉ๋๋ค.
๋๋ฒ๊ฑฐ ์คํ
JIT ์ปดํ์ผ๋ก LLDB ๋๋ฒ๊ฑฐ๋ฅผ ์์ํฉ๋๋ค:
# ํ ๋จ๊ณ๋ก p01.mojo๋ฅผ ์ปดํ์ผํ๊ณ ๋๋ฒ๊น
pixi run mojo debug solutions/p01/p01.mojo
LLDB ํ๋กฌํํธ๊ฐ ๋ณด์
๋๋ค: (lldb). ์ด์ ๋๋ฒ๊ฑฐ ์์์ ํ๋ก๊ทธ๋จ ์คํ์ ๊ฒ์ฌํ ์ค๋น๊ฐ ๋์์ต๋๋ค!
์ฒซ ๋๋ฒ๊น ๋ช ๋ น์ด๋ค
Puzzle 01์ด ์คํ๋ ๋ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ์ถ์ ํด ๋ด ์๋ค. ๋ณด์ฌ๋๋ฆฐ ๋๋ก ์ ํํ ์ด ๋ช ๋ น์ด๋ค์ ์ ๋ ฅํ๊ณ ์ถ๋ ฅ์ ๊ด์ฐฐํ์ธ์:
Step 1: main ํจ์์ ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์
(lldb) br set -n main
์ถ๋ ฅ:
Breakpoint 1: where = mojo`main, address = 0x00000000027d7530
๋๋ฒ๊ฑฐ๊ฐ main ํจ์๋ฅผ ์ฐพ์๊ณ ๊ฑฐ๊ธฐ์ ์คํ์ ์ผ์ ์ ์งํฉ๋๋ค.
Step 2: ํ๋ก๊ทธ๋จ ์์
(lldb) run
์ถ๋ ฅ:
Process 186951 launched: '/home/ubuntu/workspace/mojo-gpu-puzzles/.pixi/envs/default/bin/mojo' (x86_64)
Process 186951 stopped
* thread #1, name = 'mojo', stop reason = breakpoint 1.1
frame #0: 0x0000555557d2b530 mojo`main
mojo`main:
-> 0x555557d2b530 <+0>: pushq %rbp
0x555557d2b531 <+1>: movq %rsp, %rbp
...
ํ๋ก๊ทธ๋จ์ด ๋ธ๋ ์ดํฌํฌ์ธํธ์์ ๋ฉ์ท์ต๋๋ค. ํ์ฌ ์ด์ ๋ธ๋ฆฌ ์ฝ๋๋ฅผ ๋ณด๊ณ ์๋๋ฐ ์ด๋ ์ ์์ ๋๋ค - ๋๋ฒ๊ฑฐ๊ฐ ๊ณ ์์ค Mojo ์์ค์ ๋๋ฌํ๊ธฐ ์ ์ ์ ์์ค ๋จธ์ ์ฝ๋์์ ์์ํฉ๋๋ค.
Step 3: ์์ ๊ณผ์ ํ์
# ๋ช
๋ น์ด ํ๋๋ฅผ ๋จ๊ณ๋ณ ์คํ ์๋
(lldb) next
์ถ๋ ฅ:
Process 186951 stopped
* thread #1, name = 'mojo', stop reason = instruction step over
frame #0: 0x0000555557d2b531 mojo`main + 1
mojo`main:
-> 0x555557d2b531 <+1>: movq %rsp, %rbp
0x555557d2b534 <+4>: pushq %r15
...
์ด์ ๋ธ๋ฆฌ๋ฅผ ๋จ๊ณ๋ณ๋ก ์คํํ๋ ๊ฒ์ ์ง๋ฃจํ ์ ์์ต๋๋ค. ๋ ๊ด๋ จ ์๋ ๋ถ๋ถ์ผ๋ก ์งํํฉ์๋ค.
Step 4: Mojo ์์ค ์ฝ๋์ ๋๋ฌํ๊ธฐ ์ํด ๊ณ์
# ์์ ์ด์
๋ธ๋ฆฌ๋ฅผ ๊ฑด๋๋ฐ์ด ์ค์ ์ฝ๋๋ก ์ด๋
(lldb) continue
์ถ๋ ฅ:
Process 186951 resuming
Process 186951 stopped and restarted: thread 1 received signal: SIGCHLD
2 locations added to breakpoint 1
Process 186951 stopped
* thread #1, name = 'mojo', stop reason = breakpoint 1.3
frame #0: 0x00007fff5c01e841 JIT(0x7fff5c075000)`stdlib::builtin::_startup::__mojo_main_prototype(argc=([0] = 1), argv=0x00007fffffffa858) at _startup.mojo:95:4
Mojo์ ๋ฐํ์์ด ์ด๊ธฐํ ์ค์
๋๋ค. _startup.mojo๋ Mojo์ ๋ด๋ถ ์์ ์ฝ๋๋ฅผ ๋ํ๋
๋๋ค. SIGCHLD ์๊ทธ๋์ ์ ์์
๋๋ค - Mojo๊ฐ ๋ด๋ถ ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ์์
๋๋ค.
Step 5: ์ค์ ์ฝ๋๋ก ๊ณ์
# ํ ๋ฒ ๋ continueํด์ p01.mojo ์ฝ๋์ ๋๋ฌ!
(lldb) continue
์ถ๋ ฅ:
Process 186951 resuming
Process 186951 stopped
* thread #1, name = 'mojo', stop reason = breakpoint 1.2
frame #0: 0x00007fff5c014040 JIT(0x7fff5c075000)`p01::main(__error__=<unavailable>) at p01.mojo:24:23
21
22
23 def main():
-> 24 with DeviceContext() as ctx:
25 out = ctx.enqueue_create_buffer[dtype](SIZE)
26 out.enqueue_fill(0)
27 a = ctx.enqueue_create_buffer[dtype](SIZE)
์ด์ ์ค์ Mojo ์์ค ์ฝ๋๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ์ฃผ๋ชฉํ ์ :
- p01.mojo ํ์ผ์ 21-27๋ฒ ์ค
- ํ์ฌ ์ค 24:
with DeviceContext() as ctx: - JIT ์ปดํ์ผ:
JIT(0x7fff5c075000)์ Mojo๊ฐ ์ฝ๋๋ฅผ ์ฆ์์์ ์ปดํ์ผํ์์ ๋ํ๋
Step 6: ํ๋ก๊ทธ๋จ ์๋ฃ
# ํ๋ก๊ทธ๋จ์ ์๋ฃ๊น์ง ์คํ
(lldb) continue
์ถ๋ ฅ:
Process 186951 resuming
out: HostBuffer([10.0, 11.0, 12.0, 13.0])
expected: HostBuffer([10.0, 11.0, 12.0, 13.0])
Process 186951 exited with status = 0 (0x00000000)
๋ฐฐ์ด ๋ด์ฉ
๐ ์ถํํฉ๋๋ค! ์ฒซ GPU ํ๋ก๊ทธ๋จ ๋๋ฒ๊น ์ธ์ ์ ์๋ฃํ์ต๋๋ค. ๋ฌด์จ ์ผ์ด ์์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค:
๊ฑฐ์ณ์จ ๋๋ฒ๊น ์ฌ์ :
- ์ด์ ๋ธ๋ฆฌ๋ก ์์ - ์ ์์ค ๋๋ฒ๊น ์์๋ ์ ์์ ์ธ ํ์์ด๋ฉฐ, ๋๋ฒ๊ฑฐ๊ฐ ๋จธ์ ์์ค์์ ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณด์ฌ์ค
- Mojo ์์ ๊ณผ์ ํ์ - Mojo์ ๋ด๋ถ ์ด๊ธฐํ ์ฝ๋๊ฐ ์์์ ํ์ต
- ์์ค ์ฝ๋ ๋๋ฌ - ๊ตฌ๋ฌธ ๊ฐ์กฐ๊ฐ ๋ ์ค์ p01.mojo 21-27๋ฒ ์ค ํ์ธ
- JIT ์ปดํ์ผ ๊ด์ฐฐ - Mojo๊ฐ ์ฝ๋๋ฅผ ์ฆ์์์ ์ปดํ์ผํ๋ ๊ฒ์ ๊ด์ฐฐ
- ์ฑ๊ณต์ ์ธ ์คํ ํ์ธ - ํ๋ก๊ทธ๋จ์ด ์์๋ ์ถ๋ ฅ์ ์์ฑํจ์ ํ์ธ
LLDB ๋๋ฒ๊น ์ด ์ ๊ณตํ๋ ๊ฒ:
- โ
CPU ์ธก ๊ฐ์์ฑ:
main()ํจ์, ๋ฒํผ ํ ๋น, ๋ฉ๋ชจ๋ฆฌ ์ค์ ํ์ธ - โ ์์ค ์ฝ๋ ๊ฒ์ฌ: ์ค ๋ฒํธ๊ฐ ์๋ ์ค์ Mojo ์ฝ๋ ๋ณด๊ธฐ
- โ ๋ณ์ ๊ฒ์ฌ: ํธ์คํธ ์ธก ๋ณ์(CPU ๋ฉ๋ชจ๋ฆฌ) ๊ฐ ํ์ธ
- โ ํ๋ก๊ทธ๋จ ํ๋ฆ ์ ์ด: ์ค์ ๋ก์ง์ ์ค ๋จ์๋ก ๋จ๊ณ๋ณ ์คํ
- โ ์ค๋ฅ ์กฐ์ฌ: ์ฅ์น ์ค์ , ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฑ์ ํฌ๋์ ๋๋ฒ๊น
LLDB๊ฐ ํ ์ ์๋ ๊ฒ:
- โ GPU ์ปค๋ ๊ฒ์ฌ:
add_10ํจ์ ์คํ ๋ด๋ถ๋ก ์ง์ ๋ถ๊ฐ๋ฅ - โ ์ค๋ ๋ ์์ค ๋๋ฒ๊น : ๊ฐ๋ณ GPU ์ค๋ ๋ ๋์ ํ์ธ ๋ถ๊ฐ
- โ GPU ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ: GPU ์ค๋ ๋๊ฐ ๋ณด๋ ๋ฐ์ดํฐ ๊ฒ์ฌ ๋ถ๊ฐ
- โ ๋ณ๋ ฌ ์คํ ๋ถ์: ๊ฒฝ์ ์ํ๋ ๋๊ธฐํ ๋๋ฒ๊น ๋ถ๊ฐ
LLDB ๋๋ฒ๊น ์ ์ฌ์ฉํ ๋:
- GPU ์ฝ๋๊ฐ ์คํ๋๊ธฐ ์ ์ ํ๋ก๊ทธ๋จ์ด ํฌ๋์ํ ๋
- ๋ฒํผ ํ ๋น์ด๋ ๋ฉ๋ชจ๋ฆฌ ์ค์ ๋ฌธ์
- ํ๋ก๊ทธ๋จ ์ด๊ธฐํ์ ํ๋ฆ ์ดํด
- Mojo ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ป๊ฒ ์์๋๋์ง ํ์ต
- ๋น ๋ฅธ ํ๋กํ ํ์ดํ๊ณผ ์ฝ๋ ๋ณ๊ฒฝ ์คํ
ํต์ฌ ํต์ฐฐ: LLDB๋ ํธ์คํธ ์ธก ๋๋ฒ๊น ์ ์๋ฒฝํฉ๋๋ค - GPU ์คํ ์ ํ์ CPU์์ ์ผ์ด๋๋ ๋ชจ๋ ๊ฒ. ์ค์ GPU ์ปค๋ ๋๋ฒ๊น ์๋ ๋ค์ ์ ๊ทผ๋ฒ์ด ํ์ํฉ๋๋คโฆ
ํํ ๋ฆฌ์ผ Step 2: ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น
JIT ๋๋ฒ๊น ์ ๋ฐฐ์ ์ผ๋ ์ด์ ํ๋ก๋์ ํ๊ฒฝ์์ ์ฌ์ฉํ๋ ์ ๋ฌธ์ ์ธ ์ ๊ทผ๋ฒ์ ํ์ํฉ์๋ค.
์๋๋ฆฌ์ค: ์ฌ๋ฌ ํ์ผ์ด ์๋ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ฒ๊น ํ๊ฑฐ๋ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ๋ฐ๋ณต์ ์ผ๋ก ๋๋ฒ๊น ํด์ผ ํฉ๋๋ค. ๋จผ์ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋น๋ํ๋ฉด ๋ ๋ง์ ์ ์ด์ ๋น ๋ฅธ ๋๋ฒ๊น ๋ฐ๋ณต์ด ๊ฐ๋ฅํฉ๋๋ค.
๋๋ฒ๊ทธ ๋ฐ์ด๋๋ฆฌ ๋น๋
Step 1: ๋๋ฒ๊ทธ ์ ๋ณด๋ก ์ปดํ์ผ
# ๋๋ฒ๊ทธ ๋น๋ ์์ฑ (๋ช
ํํ ๋ช
๋ช
์ ์ฃผ๋ชฉ)
pixi run mojo build -O0 -g solutions/p01/p01.mojo -o solutions/p01/p01_debug
์ฌ๊ธฐ์ ์ผ์ด๋๋ ์ผ:
- ๐ง
-O0: ์ต์ ํ ๋นํ์ฑํ (์ ํํ ๋๋ฒ๊น ์ ๋ฐ๋์ ํ์) - ๐
-g: ๋จธ์ ์ฝ๋๋ฅผ ์์ค ์ฝ๋์ ๋งคํํ๋ ๋๋ฒ๊ทธ ์ฌ๋ณผ ํฌํจ - ๐
-o p01_debug: ๋ช ํํ๊ฒ ์ด๋ฆ ์ง์ ๋๋ฒ๊ทธ ๋ฐ์ด๋๋ฆฌ ์์ฑ
Step 2: ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น
# ๋ฏธ๋ฆฌ ๋น๋๋ ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น
pixi run mojo debug solutions/p01/p01_debug
๋ฌด์์ด ๋ค๋ฅธ๊ฐ (๊ทธ๋ฆฌ๊ณ ๋ ๋์๊ฐ)
์์ ๋น๊ต:
| JIT ๋๋ฒ๊น | ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น |
|---|---|
| ํ ๋จ๊ณ๋ก ์ปดํ์ผ + ๋๋ฒ๊น | ํ ๋ฒ ๋น๋, ์ฌ๋ฌ ๋ฒ ๋๋ฒ๊น |
| ๋๋ฆฐ ์์ (์ปดํ์ผ ์ค๋ฒํค๋) | ๋น ๋ฅธ ์์ |
| ์ปดํ์ผ ๋ฉ์์ง๊ฐ ๋๋ฒ๊ทธ ์ถ๋ ฅ๊ณผ ์์ | ๊น๋ํ ๋๋ฒ๊ฑฐ ์ถ๋ ฅ |
| ๋๋ฒ๊น ์ค ์์ฑ๋๋ ๋๋ฒ๊ทธ ์ฌ๋ณผ | ๊ณ ์ ๋ ๋๋ฒ๊ทธ ์ฌ๋ณผ |
๊ฐ์ LLDB ๋ช
๋ น์ด(br set -n main, run, continue)๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฐจ์ด๋ฅผ ๋๋ ์ ์์ต๋๋ค:
- ๋น ๋ฅธ ์์ - ์ปดํ์ผ ์ง์ฐ ์์
- ๊น๋ํ ์ถ๋ ฅ - JIT ์ปดํ์ผ ๋ฉ์์ง ์์
- ๋ ์์ธก ๊ฐ๋ฅ - ๋๋ฒ๊ทธ ์ฌ๋ณผ์ด ์คํ ๊ฐ์ ๋ณํ์ง ์์
- ์ ๋ฌธ์ ์ธ ์ํฌํ๋ก์ฐ - ํ๋ก๋์ ๋๋ฒ๊น ์ด ์ด๋ ๊ฒ ์๋ํจ
ํํ ๋ฆฌ์ผ Step 3: GPU ์ปค๋ ๋๋ฒ๊น
์ง๊ธ๊น์ง๋ CPU ํธ์คํธ ์ฝ๋ - ์ค์ , ๋ฉ๋ชจ๋ฆฌ ํ ๋น, ์ด๊ธฐํ๋ฅผ ๋๋ฒ๊น ํ์ต๋๋ค. ํ์ง๋ง ๋ณ๋ ฌ ์ฐ์ฐ์ด ์ผ์ด๋๋ ์ค์ GPU ์ปค๋์ ์ด๋จ๊น์?
๋ฌธ์ ์ : add_10 ์ปค๋์ ์ ์ฌ์ ์ผ๋ก ์์ฒ ๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ์คํ๋๋ GPU์์ ์คํ๋ฉ๋๋ค. LLDB๋ GPU์ ๋ณ๋ ฌ ์คํ ํ๊ฒฝ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
ํด๊ฒฐ์ฑ : CUDA-GDB - GPU ์ค๋ ๋, GPU ๋ฉ๋ชจ๋ฆฌ, ๋ณ๋ ฌ ์คํ์ ์ดํดํ๋ ์ ๋ฌธ ๋๋ฒ๊ฑฐ์ ๋๋ค.
CUDA-GDB๊ฐ ํ์ํ ์ด์
GPU ๋๋ฒ๊น ์ด ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅธ ์ด์ ๋ฅผ ์ดํดํฉ์๋ค:
CPU ๋๋ฒ๊น (LLDB):
- ์์ฐจ์ ์ผ๋ก ์คํ๋๋ ๋จ์ผ ์ค๋ ๋
- ์ถ์ ํ ์ฝ ์คํ์ด ํ๋๋ฟ
- ๋จ์ํ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ
- ๋ณ์๊ฐ ๋จ์ผ ๊ฐ์ ๊ฐ์ง
GPU ๋๋ฒ๊น (CUDA-GDB):
- ๋ณ๋ ฌ๋ก ์คํ๋๋ ์์ฒ ๊ฐ์ ์ค๋ ๋
- ์ฌ๋ฌ ์ฝ ์คํ (์ค๋ ๋๋น ํ๋)
- ๋ณต์กํ ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ (์ ์ญ, ๊ณต์ , ๋ก์ปฌ, ๋ ์ง์คํฐ)
- ๊ฐ์ ๋ณ์๊ฐ ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง
์ค์ ์: add_10 ์ปค๋์์ thread_idx.x ๋ณ์๋ ๊ฐ ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง๋๋ค - ์ค๋ ๋ 0์ 0์, ์ค๋ ๋ 1์ 1์ ๋ณด๋ ์์
๋๋ค. CUDA-GDB๋ง์ด ์ด ๋ณ๋ ฌ ํ์ค์ ๋ณด์ฌ์ค ์ ์์ต๋๋ค.
CUDA-GDB ๋๋ฒ๊ฑฐ ์คํ
Step 1: GPU ์ปค๋ ๋๋ฒ๊น ์์
์ ๊ทผ๋ฒ์ ์ ํํ์ธ์:
# ์ด๋ฏธ ์คํํ๋์ง ํ์ธ (ํ ๋ฒ์ด๋ฉด ์ถฉ๋ถ)
pixi run setup-cuda-gdb
# JIT + CUDA-GDB ์ฌ์ฉ (์์ ์ ๊ทผ๋ฒ 2)
pixi run mojo debug --cuda-gdb --break-on-launch solutions/p01/p01.mojo
ํ์ต๊ณผ ๋น ๋ฅธ ๋ฐ๋ณต์ ์ ํฉํ JIT + CUDA-GDB ์ ๊ทผ๋ฒ์ ์ฌ์ฉํฉ๋๋ค.
Step 2: ์คํํ๊ณ GPU ์ปค๋ ์ง์ ์ ์๋ ์ ์ง
CUDA-GDB ํ๋กฌํํธ๋ ์ด๋ ๊ฒ ๋ณด์
๋๋ค: (cuda-gdb). ํ๋ก๊ทธ๋จ์ ์์ํฉ๋๋ค:
# ํ๋ก๊ทธ๋จ ์คํ - GPU ์ปค๋์ด ์คํ๋ ๋ ์๋์ผ๋ก ์ ์ง
(cuda-gdb) run
์ถ๋ ฅ:
Starting program: /home/ubuntu/workspace/mojo-gpu-puzzles/.pixi/envs/default/bin/mojo...
[Thread debugging using libthread_db enabled]
...
[Switching focus to CUDA kernel 0, grid 1, block (0,0,0), thread (0,0,0)]
CUDA thread hit application kernel entry function breakpoint, p01_add_10_UnsafePointer...
<<<(1,1,1),(4,1,1)>>> (output=0x302000000, a=0x302000200) at p01.mojo:16
16 i = thread_idx.x
์ฑ๊ณต! GPU ์ปค๋ ๋ด๋ถ์์ ์๋์ผ๋ก ์ ์งํ์ต๋๋ค! --break-on-launch ํ๋๊ทธ๊ฐ ์ปค๋ ์คํ์ ๊ฐ์งํ๊ณ ์ด์ i = thread_idx.x๊ฐ ์คํ๋๋ 16๋ฒ ์ค์ ์์ต๋๋ค.
์ค์: break add_10์ฒ๋ผ ์๋์ผ๋ก ๋ธ๋ ์ดํฌํฌ์ธํธ๋ฅผ ์ค์ ํ ํ์ ์์ต๋๋ค - ์ปค๋ ์ง์
๋ธ๋ ์ดํฌํฌ์ธํธ๋ ์๋์
๋๋ค. GPU ์ปค๋ ํจ์๋ CUDA-GDB์์ ๋งน๊ธ๋ง๋ ์ด๋ฆ(p01_add_10_UnsafePointer... ๊ฐ์)์ ๊ฐ์ง์ง๋ง, ์ด๋ฏธ ์ปค๋ ์์ ์์ผ๋ฏ๋ก ๋ฐ๋ก ๋๋ฒ๊น
์ ์์ํ ์ ์์ต๋๋ค.
Step 3: ๋ณ๋ ฌ ์คํ ํ์
# ๋ธ๋ ์ดํฌํฌ์ธํธ์์ ์ผ์ ์ ์ง๋ ๋ชจ๋ GPU ์ค๋ ๋ ๋ณด๊ธฐ
(cuda-gdb) info cuda threads
์ถ๋ ฅ:
BlockIdx ThreadIdx To BlockIdx To ThreadIdx Count PC Filename Line
Kernel 0
* (0,0,0) (0,0,0) (0,0,0) (3,0,0) 4 0x00007fffd326fb70 /home/ubuntu/workspace/mojo-gpu-puzzles/solutions/p01/p01.mojo 16
์๋ฒฝํฉ๋๋ค! Puzzle 01์ ๋ชจ๋ 4๊ฐ ๋ณ๋ ฌ GPU ์ค๋ ๋๋ฅผ ๋ณด์ฌ์ค๋๋ค:
*๊ฐ ํ์ฌ ์ค๋ ๋ ํ์:(0,0,0)- ๋๋ฒ๊น ์ค์ธ ์ค๋ ๋- ์ค๋ ๋ ๋ฒ์:
(0,0,0)์์(3,0,0)๊น์ง - ๋ธ๋ก์ ๋ชจ๋ 4๊ฐ ์ค๋ ๋ - Count:
4- ์ฝ๋์THREADS_PER_BLOCK = 4์ ์ผ์น - ๊ฐ์ ์์น: ๋ชจ๋ ์ค๋ ๋๊ฐ
p01.mojo์ 16๋ฒ ์ค์์ ์ผ์ ์ ์ง
Step 4: ์ปค๋์ ๋จ๊ณ๋ณ ์คํํ๊ณ ๋ณ์ ๊ฒ์ฌ
# 'next'๋ก ์ฝ๋ ๋จ๊ณ๋ณ ์คํ ('step'์ ๋ด๋ถ๋ก ๋ค์ด๊ฐ)
(cuda-gdb) next
์ถ๋ ฅ:
p01_add_10_UnsafePointer... at p01.mojo:17
17 output[i] = a[i] + 10.0
# ๋ก์ปฌ ๋ณ์๋ ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ์์ ์๋!
(cuda-gdb) print i
์ถ๋ ฅ:
$1 = 0 # ์ด ์ค๋ ๋์ ์ธ๋ฑ์ค (thread_idx.x ๊ฐ ์บก์ฒ)
# GPU ๋ด์ฅ ๋ณ์๋ ์๋ํ์ง ์์ง๋ง ํ์ ์์
(cuda-gdb) print thread_idx.x
์ถ๋ ฅ:
No symbol "thread_idx" in current context.
# ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํด ์ค๋ ๋๋ณ ๋ฐ์ดํฐ ์ ๊ทผ
(cuda-gdb) print a[i] # ์ด ์ค๋ ๋์ ์
๋ ฅ: a[0]
์ถ๋ ฅ:
$2 = {0} # ์
๋ ฅ ๊ฐ (Mojo ์ค์นผ๋ผ ํ์)
(cuda-gdb) print output[i] # ์ฐ์ฐ ์ ์ด ์ค๋ ๋์ ์ถ๋ ฅ
์ถ๋ ฅ:
$3 = {0} # ์์ง 0 - ์ฐ์ฐ์ด ์์ง ์คํ๋์ง ์์!
# ์ฐ์ฐ ์ค ์คํ
(cuda-gdb) next
์ถ๋ ฅ:
13 fn add_10( # ์ฐ์ฐ ํ ํจ์ ์๊ทธ๋์ฒ ์ค๋ก ์ด๋
# ์ด์ ๊ฒฐ๊ณผ ํ์ธ
(cuda-gdb) print output[i]
์ถ๋ ฅ:
$4 = {10} # ์ด์ ๊ณ์ฐ๋ ๊ฒฐ๊ณผ ํ์: 0 + 10 = 10
# ํจ์ ํ๋ผ๋ฏธํฐ๋ ์ฌ์ ํ ์ฌ์ฉ ๊ฐ๋ฅ
(cuda-gdb) print a
์ถ๋ ฅ:
$5 = (!pop.scalar<f32> * @register) 0x302000200
Step 5: ๋ณ๋ ฌ ์ค๋ ๋ ๊ฐ ์ด๋
# ๋ค๋ฅธ ์ค๋ ๋๋ก ์ ํํด์ ์คํ ํ์ธ
(cuda-gdb) cuda thread (1,0,0)
์ถ๋ ฅ:
[Switching focus to CUDA kernel 0, grid 1, block (0,0,0), thread (1,0,0), device 0, sm 0, warp 0, lane 1]
13 fn add_10( # ์ค๋ ๋ 1๋ ํจ์ ์๊ทธ๋์ฒ์ ์์
# ์ค๋ ๋์ ๋ก์ปฌ ๋ณ์ ํ์ธ
(cuda-gdb) print i
์ถ๋ ฅ:
$5 = 1 # ์ค๋ ๋ 1์ ์ธ๋ฑ์ค (์ค๋ ๋ 0๊ณผ ๋ค๋ฆ!)
# ์ด ์ค๋ ๋๊ฐ ์ฒ๋ฆฌํ๋ ๊ฒ ๊ฒ์ฌ
(cuda-gdb) print a[i] # ์ด ์ค๋ ๋์ ์
๋ ฅ: a[1]
์ถ๋ ฅ:
$6 = {1} # ์ค๋ ๋ 1์ ์
๋ ฅ ๊ฐ
# ์ค๋ ๋ 1์ ์ฐ์ฐ์ ์ด๋ฏธ ์๋ฃ (๋ณ๋ ฌ ์คํ!)
(cuda-gdb) print output[i] # ์ด ์ค๋ ๋์ ์ถ๋ ฅ: output[1]
์ถ๋ ฅ:
$7 = {11} # 1 + 10 = 11 (์ด๋ฏธ ๊ณ์ฐ๋จ)
# ์ต๊ณ ์ ๊ธฐ๋ฒ: ๋ชจ๋ ์ค๋ ๋ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ์ ๋ณด๊ธฐ
(cuda-gdb) print output[0]@4
์ถ๋ ฅ:
$8 = {{10}, {11}, {12}, {13}} # ๋ชจ๋ 4๊ฐ ์ค๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ช
๋ น์ด๋ก!
(cuda-gdb) print a[0]@4
์ถ๋ ฅ:
$9 = {{0}, {1}, {2}, {3}} # ๋น๊ต๋ฅผ ์ํ ๋ชจ๋ ์
๋ ฅ ๊ฐ
# ๋๋ฌด ๋ฉ๋ฆฌ ์งํํ๋ฉด CUDA ์ปจํ
์คํธ๋ฅผ ์์ต๋๋ค
(cuda-gdb) next
์ถ๋ ฅ:
[Switching to Thread 0x7ffff7e25840 (LWP 306942)] # ํธ์คํธ ์ค๋ ๋๋ก ๋ณต๊ท
0x00007fffeca3f831 in ?? () from /lib/x86_64-linux-gnu/libcuda.so.1
(cuda-gdb) print output[i]
์ถ๋ ฅ:
No symbol "output" in current context. # GPU ์ปจํ
์คํธ๋ฅผ ์์!
์ด ๋๋ฒ๊น ์ธ์ ์ ํต์ฌ ํต์ฐฐ:
- ๐คฏ ๋ณ๋ ฌ ์คํ์ ์ง์ง์ ๋๋ค - ์ค๋ ๋ (1,0,0)์ผ๋ก ์ ํํ๋ฉด ์ด๋ฏธ ์ฐ์ฐ์ด ์๋ฃ๋์ด ์์ต๋๋ค!
- ๊ฐ ์ค๋ ๋๋ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๋ด
๋๋ค -
i=0vsi=1,a[i]={0}vsa[i]={1},output[i]={10}vsoutput[i]={11} - ๋ฐฐ์ด ๊ฒ์ฌ๊ฐ ๊ฐ๋ ฅํฉ๋๋ค -
print output[0]@4๋ก ๋ชจ๋ ์ค๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค:{{10}, {11}, {12}, {13}} - GPU ์ปจํ ์คํธ๋ ๊นจ์ง๊ธฐ ์ฝ์ต๋๋ค - ๋๋ฌด ๋ฉ๋ฆฌ ์งํํ๋ฉด ํธ์คํธ ์ค๋ ๋๋ก ๋์๊ฐ GPU ๋ณ์์ ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค
์ด๊ฒ์ด ๋ฐ๋ก ๋ณ๋ ฌ ์ปดํจํ ์ ๋ณธ์ง์ ๋๋ค: ๊ฐ์ ์ฝ๋, ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ๋ฐ์ดํฐ, ๋์ ์คํ.
CUDA-GDB๋ก ๋ฐฐ์ด ๋ด์ฉ
๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ๋ก GPU ์ปค๋ ์คํ ๋๋ฒ๊น ์ ์๋ฃํ์ต๋๋ค. ๋ค์์ ์ค์ ๋ก ์๋ํ๋ ๊ธฐ๋ฅ๋ค์ ๋๋ค:
์ต๋ํ GPU ๋๋ฒ๊น ๋ฅ๋ ฅ:
- โ
GPU ์ปค๋ ์๋ ๋๋ฒ๊น
-
--break-on-launch๊ฐ ์ปค๋ ์ง์ ์์ ์์ ์ ์งํฉ๋๋ค - โ
GPU ์ค๋ ๋ ๊ฐ ์ด๋ -
cuda thread๋ก ์ปจํ ์คํธ๋ฅผ ์ ํํฉ๋๋ค - โ
๋ก์ปฌ ๋ณ์ ์ ๊ทผ -
-O0 -g๋ก ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ์์print i๊ฐ ์๋ํฉ๋๋ค - โ
์ค๋ ๋๋ณ ๋ฐ์ดํฐ ๊ฒ์ฌ - ๊ฐ ์ค๋ ๋๊ฐ ์๋ก ๋ค๋ฅธ
i,a[i],output[i]๊ฐ์ ๋ณด์ฌ์ค๋๋ค - โ
๋ชจ๋ ์ค๋ ๋ ๊ฒฐ๊ณผ ๋ณด๊ธฐ -
print output[0]@4๋ก{{10}, {11}, {12}, {13}}์ ํ ๋ฒ์ ํ์ํฉ๋๋ค - โ
GPU ์ฝ๋ ๋จ๊ณ๋ณ ์คํ -
next๊ฐ ์ฐ์ฐ์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค - โ ๋ณ๋ ฌ ์คํ ํ์ธ - ์ค๋ ๋๊ฐ ๋์์ ์คํ๋ฉ๋๋ค (์ ํํ๋ฉด ๋ค๋ฅธ ์ค๋ ๋๋ ์ด๋ฏธ ๊ณ์ฐ ์๋ฃ)
- โ
ํจ์ ํ๋ผ๋ฏธํฐ ์ ๊ทผ -
output๊ณผaํฌ์ธํฐ๋ฅผ ๊ฒ์ฌํ ์ ์์ต๋๋ค - โ GPU ๋ด์ฅ ๋ณ์ ์ฌ์ฉ ๋ถ๊ฐ -
thread_idx.x,blockIdx.x๋ฑ์ ์๋ํ์ง ์์ต๋๋ค (ํ์ง๋ง ๋ก์ปฌ ๋ณ์๋ ์๋ํฉ๋๋ค!) - ๐ Mojo ์ค์นผ๋ผ ํ์ - ๊ฐ์ด
10.0๋์{10}์ผ๋ก ํ์๋ฉ๋๋ค - โ ๏ธ ๊นจ์ง๊ธฐ ์ฌ์ด GPU ์ปจํ ์คํธ - ๋๋ฌด ๋ฉ๋ฆฌ ์งํํ๋ฉด GPU ๋ณ์์ ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค
ํต์ฌ ํต์ฐฐ:
- ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ (
mojo build -O0 -g)๋ ํ์์ ๋๋ค - ๋ก์ปฌ ๋ณ์๊ฐ ๋ณด์กด๋ฉ๋๋ค @N์ ์ฌ์ฉํ ๋ฐฐ์ด ๊ฒ์ฌ - ๋ชจ๋ ๋ณ๋ ฌ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ์ ๋ณด๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค- GPU ๋ด์ฅ ๋ณ์๋ ์์ต๋๋ค - ํ์ง๋ง
i๊ฐ์ ๋ก์ปฌ ๋ณ์๊ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค - Mojo๋
{value}ํ์์ ์ฌ์ฉํฉ๋๋ค - ์ค์นผ๋ผ๊ฐ10.0๋์{10}์ผ๋ก ํ์๋ฉ๋๋ค - ๋จ๊ณ๋ณ ์คํ์ ์ฃผ์ํ์ธ์ - GPU ์ปจํ ์คํธ๋ฅผ ์๊ณ ํธ์คํธ ์ค๋ ๋๋ก ๋์๊ฐ๊ธฐ ์ฝ์ต๋๋ค
์ค์ ๋๋ฒ๊น ๊ธฐ๋ฒ๋ค
์ด์ ์ค์ GPU ํ๋ก๊ทธ๋๋ฐ์์ ๋ง์ฃผ์น๊ฒ ๋ ์ค์ฉ์ ์ธ ๋๋ฒ๊น ์๋๋ฆฌ์ค๋ฅผ ์ดํด๋ด ์๋ค:
๊ธฐ๋ฒ 1: ์ค๋ ๋ ๊ฒฝ๊ณ ํ์ธ
# ๋ชจ๋ 4๊ฐ ์ค๋ ๋๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ณ์ฐํ๋์ง ํ์ธ
(cuda-gdb) print output[0]@4
์ถ๋ ฅ:
$8 = {{10}, {11}, {12}, {13}} # ๋ชจ๋ 4๊ฐ ์ค๋ ๋๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ณ์ฐ
# ์ ํจ ๋ฒ์๋ฅผ ๋์ด ํ์ธํ์ฌ ๋ฒ์ ์ด๊ณผ ๋ฌธ์ ๊ฐ์ง
(cuda-gdb) print output[0]@5
์ถ๋ ฅ:
$9 = {{10}, {11}, {12}, {13}, {0}} # ์์ 4๋ ์ด๊ธฐํ๋์ง ์์ (์ข์!)
# ์
๋ ฅ๊ณผ ๋น๊ตํ์ฌ ์ฐ์ฐ ๊ฒ์ฆ
(cuda-gdb) print a[0]@4
์ถ๋ ฅ:
$10 = {{0}, {1}, {2}, {3}} # ์
๋ ฅ ๊ฐ: 0+10=10, 1+10=11 ๋ฑ
์ด๊ฒ์ด ์ค์ํ ์ด์ : ๋ฒ์ ์ด๊ณผ ์ ๊ทผ์ GPU ํฌ๋์์ ๊ฐ์ฅ ํํ ์์ธ์ ๋๋ค. ์ด๋ฐ ๋๋ฒ๊น ๋จ๊ณ๋ก ์ผ์ฐ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
๊ธฐ๋ฒ 2: ์ค๋ ๋ ๊ตฌ์ฑ ์ดํด
# ์ค๋ ๋๊ฐ ๋ธ๋ก์ผ๋ก ์ด๋ป๊ฒ ๊ตฌ์ฑ๋๋์ง ๋ณด๊ธฐ
(cuda-gdb) info cuda blocks
์ถ๋ ฅ:
BlockIdx To BlockIdx Count State
Kernel 0
* (0,0,0) (0,0,0) 1 running
# ํ์ฌ ๋ธ๋ก์ ๋ชจ๋ ์ค๋ ๋ ๋ณด๊ธฐ
(cuda-gdb) info cuda threads
์ถ๋ ฅ์ ์ด๋ค ์ค๋ ๋๊ฐ ํ์ฑ ์ํ์ธ์ง, ์ ์ง๋์๋์ง, ์ค๋ฅ๊ฐ ์๋์ง ๋ณด์ฌ์ค๋๋ค.
์ด๊ฒ์ด ์ค์ํ ์ด์ : ์ค๋ ๋ ๋ธ๋ก ๊ตฌ์ฑ์ ์ดํดํ๋ฉด ๋๊ธฐํ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๊ธฐ๋ฒ 3: ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ๋ถ์
# GPU ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ํ์ธ:
(cuda-gdb) print a # ์
๋ ฅ ๋ฐฐ์ด GPU ํฌ์ธํฐ
์ถ๋ ฅ:
$9 = (!pop.scalar<f32> * @register) 0x302000200
(cuda-gdb) print output # ์ถ๋ ฅ ๋ฐฐ์ด GPU ํฌ์ธํฐ
์ถ๋ ฅ:
$10 = (!pop.scalar<f32> * @register) 0x302000000
# ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ํ์ธ:
(cuda-gdb) print a[i] # ๊ฐ ์ค๋ ๋๊ฐ 'i'๋ฅผ ์ฌ์ฉํด ์์ ์ ์์์ ์ ๊ทผ
์ถ๋ ฅ:
$11 = {0} # ์ค๋ ๋์ ์
๋ ฅ ๋ฐ์ดํฐ
์ด๊ฒ์ด ์ค์ํ ์ด์ : ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ์ฑ๋ฅ๊ณผ ์ ํ์ฑ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ์๋ชป๋ ํจํด์ ๊ฒฝ์ ์ํ๋ ํฌ๋์๋ฅผ ์ด๋ํฉ๋๋ค.
๊ธฐ๋ฒ 4: ๊ฒฐ๊ณผ ๊ฒ์ฆ ๋ฐ ์๋ฃ
# ์ปค๋ ์คํ์ ๋จ๊ณ๋ณ๋ก ์คํํ ํ ์ต์ข
๊ฒฐ๊ณผ ํ์ธ
(cuda-gdb) print output[0]@4
์ถ๋ ฅ:
$11 = {10.0, 11.0, 12.0, 13.0} # ์๋ฒฝ! ๊ฐ ์์๊ฐ 10 ์ฆ๊ฐ
# ํ๋ก๊ทธ๋จ์ ์ ์์ ์ผ๋ก ์๋ฃ
(cuda-gdb) continue
์ถ๋ ฅ:
...ํ๋ก๊ทธ๋จ ์ถ๋ ฅ์ด ์ฑ๊ณต ํ์...
# ๋๋ฒ๊ฑฐ ์ข
๋ฃ
(cuda-gdb) exit
์ค์ ๋ถํฐ ๊ฒฐ๊ณผ๊น์ง GPU ์ปค๋ ์คํ ๋๋ฒ๊น ์ ์๋ฃํ์ต๋๋ค.
GPU ๋๋ฒ๊น ์ฌ์ : ํต์ฌ ํต์ฐฐ
ํฌ๊ด์ ์ธ GPU ๋๋ฒ๊น ํํ ๋ฆฌ์ผ์ ์๋ฃํ์ต๋๋ค. ๋ณ๋ ฌ ์ปดํจํ ์ ๋ํด ๋ฐ๊ฒฌํ ๋ด์ฉ์ ๋๋ค:
๋ณ๋ ฌ ์คํ์ ๋ํ ๊น์ ํต์ฐฐ
-
์ค๋ ๋ ์ธ๋ฑ์ฑ์ ์ค์ :
thread_idx.x๊ฐ ๋ณ๋ ฌ ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ๊ฐ(0, 1, 2, 3โฆ)์ ๊ฐ๋ ๊ฒ์ ์ด๋ก ์ด ์๋ ์ง์ ํ์ธํ์ต๋๋ค -
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ํ์ : ๊ฐ ์ค๋ ๋๊ฐ
a[thread_idx.x]์์ ์ฝ๊ณoutput[thread_idx.x]์ ์ฐ๋ฉฐ, ์ถฉ๋ ์์ด ์๋ฒฝํ ๋ฐ์ดํฐ ๋ณ๋ ฌ์ฑ์ ๋ง๋ค์ด๋ ๋๋ค -
๋ณ๋ ฌ ์คํ์ ์ดํด: ์์ฒ ๊ฐ์ ์ค๋ ๋๊ฐ ๋์ผํ ์ปค๋ ์ฝ๋๋ฅผ ๋์์ ์คํํ๋ฉด์ ๊ฐ๊ฐ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ ์์๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค
-
GPU ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ: ๋ฐฐ์ด์ ์ ์ญ GPU ๋ฉ๋ชจ๋ฆฌ์ ์์ด ๋ชจ๋ ์ค๋ ๋๊ฐ ์ ๊ทผํ ์ ์์ง๋ง, ์ค๋ ๋๋ณ ์ธ๋ฑ์ฑ์ ์ฌ์ฉํฉ๋๋ค
๋ชจ๋ ํผ์ฆ์ ์ ์ฉ๋๋ ๋๋ฒ๊น ๊ธฐ๋ฒ
Puzzle 01๋ถํฐ Puzzle 08, ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ดํ๊น์ง ๋ณดํธ์ ์ผ๋ก ์ ์ฉ๋๋ ๊ธฐ๋ฒ์ ์ต๋ํ์ต๋๋ค:
- CPU ์ธก ๋ฌธ์ (์ฅ์น ์ค์ , ๋ฉ๋ชจ๋ฆฌ ํ ๋น)๋ LLDB๋ก ์์ํฉ๋๋ค
- GPU ์ปค๋ ๋ฌธ์ (์ค๋ ๋ ๋์, ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ)๋ CUDA-GDB๋ก ์ ํํฉ๋๋ค
- ํน์ ์ค๋ ๋๋ ๋ฐ์ดํฐ ์กฐ๊ฑด์ ์ง์คํ๋ ค๋ฉด ์กฐ๊ฑด๋ถ ๋ธ๋ ์ดํฌํฌ์ธํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค
- ๋ณ๋ ฌ ์คํ ํจํด์ ์ดํดํ๋ ค๋ฉด ์ค๋ ๋ ๊ฐ ์ด๋์ ํ์ฉํฉ๋๋ค
- ๊ฒฝ์ ์ํ์ ๋ฒ์ ์ด๊ณผ ์ค๋ฅ๋ฅผ ์ก์ผ๋ ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ํ์ธํฉ๋๋ค
ํ์ฅ์ฑ: ์ด ๊ธฐ๋ฒ๋ค์ ๋ค์ ๋ชจ๋ ์ํฉ์์ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค:
- Puzzle 01: ๊ฐ๋จํ ๋ง์ ์ ํ๋ 4๊ฐ ์์ ๋ฐฐ์ด
- Puzzle 08: ์ค๋ ๋ ๋๊ธฐํ๊ฐ ํ์ํ ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฐ์ฐ
- ํ๋ก๋์ ์ฝ๋: ์ ๊ตํ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ ๋ฐฑ๋ง ๊ฐ ์์ ๋ฐฐ์ด
ํ์ ๋๋ฒ๊น ๋ช ๋ น์ด ์ฐธ์กฐ
๋๋ฒ๊น ์ํฌํ๋ก์ฐ๋ฅผ ๋ฐฐ์ ์ผ๋, ์ผ์์ ์ธ ๋๋ฒ๊น ์ธ์ ์์ ์ธ ๋น ๋ฅธ ์ฐธ์กฐ ๊ฐ์ด๋๋ฅผ ๋๋ฆฝ๋๋ค. ์ด ์น์ ์ ๋ถ๋งํฌํ์ธ์!
GDB ๋ช ๋ น์ด ์ฝ์ด (์๊ฐ ์ ์ฝ!)
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋จ์ถํค๋ก ๋ ๋น ๋ฅธ ๋๋ฒ๊น :
| ์ฝ์ด | ์ ์ฒด ๋ช ๋ น์ด | ๊ธฐ๋ฅ |
|---|---|---|
r | run | ํ๋ก๊ทธ๋จ ์์/์คํ |
c | continue | ์คํ ์ฌ๊ฐ |
n | next | ์คํ ์ค๋ฒ (๊ฐ์ ๋ ๋ฒจ) |
s | step | ํจ์ ๋ด๋ถ๋ก ์ง์ |
b | break | ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์ |
p | print | ๋ณ์ ๊ฐ ์ถ๋ ฅ |
l | list | ์์ค ์ฝ๋ ํ์ |
q | quit | ๋๋ฒ๊ฑฐ ์ข ๋ฃ |
์์:
(cuda-gdb) r # 'run' ๋์
(cuda-gdb) b 39 # 'break 39' ๋์
(cuda-gdb) p thread_id # 'print thread_id' ๋์
(cuda-gdb) n # 'next' ๋์
(cuda-gdb) c # 'continue' ๋์
โก Pro ํ: ์ฝ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ฒ๊น ์๋๊ฐ 3-5๋ฐฐ ๋นจ๋ผ์ง๋๋ค!
LLDB ๋ช ๋ น์ด (CPU ํธ์คํธ ์ฝ๋ ๋๋ฒ๊น )
์ธ์ ์ฌ์ฉ: ์ฅ์น ์ค์ , ๋ฉ๋ชจ๋ฆฌ ํ ๋น, ํ๋ก๊ทธ๋จ ํ๋ฆ, ํธ์คํธ ์ธก ํฌ๋์ ๋๋ฒ๊น
์คํ ์ ์ด
(lldb) run # ํ๋ก๊ทธ๋จ ์คํ
(lldb) continue # ์คํ ์ฌ๊ฐ (๋ณ์นญ: c)
(lldb) step # ํจ์ ๋ด๋ถ๋ก ์ง์
(์์ค ๋ ๋ฒจ)
(lldb) next # ํจ์ ๊ฑด๋๋ฐ๊ธฐ (์์ค ๋ ๋ฒจ)
(lldb) finish # ํ์ฌ ํจ์์์ ๋๊ฐ๊ธฐ
๋ธ๋ ์ดํฌํฌ์ธํธ ๊ด๋ฆฌ
(lldb) br set -n main # main ํจ์์ ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์
(lldb) br set -n function_name # ์ด๋ค ํจ์์๋ ๋ธ๋ ์ดํฌํฌ์ธํธ ์ค์
(lldb) br list # ๋ชจ๋ ๋ธ๋ ์ดํฌํฌ์ธํธ ํ์
(lldb) br delete 1 # ๋ธ๋ ์ดํฌํฌ์ธํธ #1 ์ญ์
(lldb) br disable 1 # ๋ธ๋ ์ดํฌํฌ์ธํธ #1 ์์ ๋นํ์ฑํ
๋ณ์ ๊ฒ์ฌ
(lldb) print variable_name # ๋ณ์ ๊ฐ ํ์
(lldb) print pointer[offset] # ํฌ์ธํฐ ์ญ์ฐธ์กฐ
(lldb) print array[0]@4 # ์ฒซ 4๊ฐ ๋ฐฐ์ด ์์ ํ์
CUDA-GDB ๋ช ๋ น์ด (GPU ์ปค๋ ๋๋ฒ๊น )
์ธ์ ์ฌ์ฉ: GPU ์ปค๋, ์ค๋ ๋ ๋์, ๋ณ๋ ฌ ์คํ, GPU ๋ฉ๋ชจ๋ฆฌ ๋ฌธ์ ๋๋ฒ๊น
GPU ์ํ ๊ฒ์ฌ
(cuda-gdb) info cuda threads # ๋ชจ๋ GPU ์ค๋ ๋์ ์ํ ํ์
(cuda-gdb) info cuda blocks # ๋ชจ๋ ์ค๋ ๋ ๋ธ๋ก ํ์
(cuda-gdb) cuda kernel # ํ์ฑ GPU ์ปค๋ ๋์ด
์ค๋ ๋ ํ์ (๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ!)
(cuda-gdb) cuda thread (0,0,0) # ํน์ ์ค๋ ๋ ์ขํ๋ก ์ ํ
(cuda-gdb) cuda block (0,0) # ํน์ ๋ธ๋ก์ผ๋ก ์ ํ
(cuda-gdb) cuda thread # ํ์ฌ ์ค๋ ๋ ์ขํ ํ์
์ค๋ ๋๋ณ ๋ณ์ ๊ฒ์ฌ
# ๋ก์ปฌ ๋ณ์์ ํจ์ ํ๋ผ๋ฏธํฐ:
(cuda-gdb) print i # ๋ก์ปฌ ์ค๋ ๋ ์ธ๋ฑ์ค ๋ณ์
(cuda-gdb) print output # ํจ์ ํ๋ผ๋ฏธํฐ ํฌ์ธํฐ
(cuda-gdb) print a # ํจ์ ํ๋ผ๋ฏธํฐ ํฌ์ธํฐ
GPU ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ
# ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ฐฐ์ด ๊ฒ์ฌ (์ค์ ๋ก ์๋ํ๋ ๊ฒ):
(cuda-gdb) print array[i] # ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ค๋ ๋๋ณ ๋ฐฐ์ด ์ ๊ทผ
(cuda-gdb) print array[0]@4 # ์ฌ๋ฌ ์์ ๋ณด๊ธฐ: {{val1}, {val2}, {val3}, {val4}}
๊ณ ๊ธ GPU ๋๋ฒ๊น
# ๋ฉ๋ชจ๋ฆฌ ๊ฐ์
(cuda-gdb) watch array[i] # ๋ฉ๋ชจ๋ฆฌ ๋ณ๊ฒฝ ์ ์ค๋จ
(cuda-gdb) rwatch array[i] # ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ ์ ์ค๋จ
๋น ๋ฅธ ์ฐธ์กฐ: ๋๋ฒ๊น ๊ฒฐ์ ํธ๋ฆฌ
๐ค ์ด๋ค ์ ํ์ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๊ณ ์๋์?
GPU ์ฝ๋ ์คํ ์ ์ ํ๋ก๊ทธ๋จ์ด ํฌ๋์
โ LLDB ๋๋ฒ๊น ์ฌ์ฉ
pixi run mojo debug your_program.mojo
GPU ์ปค๋์ด ์๋ชป๋ ๊ฒฐ๊ณผ ์์ฑ
โ ์กฐ๊ฑด๋ถ ๋ธ๋ ์ดํฌํฌ์ธํธ์ ํจ๊ป CUDA-GDB ์ฌ์ฉ
pixi run mojo debug --cuda-gdb --break-on-launch your_program.mojo
์ฑ๋ฅ ๋ฌธ์ ๋ ๊ฒฝ์ ์ํ
โ ์ฌํ์ฑ์ ์ํด ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น ์ฌ์ฉ
pixi run mojo build -O0 -g your_program.mojo -o debug_binary
pixi run mojo debug --cuda-gdb --break-on-launch debug_binary
GPU ๋๋ฒ๊น ์ ํต์ฌ์ ๋ฐฐ์ ์ต๋๋ค
GPU ๋๋ฒ๊น ๊ธฐ์ด์ ๋ํ ํฌ๊ด์ ์ธ ํํ ๋ฆฌ์ผ์ ์๋ฃํ์ต๋๋ค. ๋ค์์ ๋ฌ์ฑํ ๋ด์ฉ์ ๋๋ค:
์ต๋ํ ๊ธฐ์
๋ค์ค ๋ ๋ฒจ ๋๋ฒ๊น ์ง์:
- โ LLDB๋ก CPU ํธ์คํธ ๋๋ฒ๊น - ์ฅ์น ์ค์ , ๋ฉ๋ชจ๋ฆฌ ํ ๋น, ํ๋ก๊ทธ๋จ ํ๋ฆ ๋๋ฒ๊น
- โ CUDA-GDB๋ก GPU ์ปค๋ ๋๋ฒ๊น - ๋ณ๋ ฌ ์ค๋ ๋, GPU ๋ฉ๋ชจ๋ฆฌ, ๊ฒฝ์ ์ํ ๋๋ฒ๊น
- โ JIT vs ๋ฐ์ด๋๋ฆฌ ๋๋ฒ๊น - ์ํฉ์ ๋ง๋ ์ ๊ทผ๋ฒ ์ ํ
- โ pixi๋ก ํ๊ฒฝ ๊ด๋ฆฌ - ์ผ๊ด๋๊ณ ์ ๋ขฐํ ์ ์๋ ๋๋ฒ๊น ์ค์ ๋ณด์ฅ
์ค์ ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ ํต์ฐฐ:
- ์ค๋ ๋์ ์ค์ ๋์ ํ์ธ - ๋ณ๋ ฌ ์ค๋ ๋๋ง๋ค
thread_idx.x๊ฐ ๋ค๋ฅธ ๊ฐ์ ๊ฐ๋ ๊ฒ์ ์ง์ ๋ชฉ๊ฒฉํ์ต๋๋ค - ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ ์ดํด - ์ ์ญ GPU ๋ฉ๋ชจ๋ฆฌ, ๊ณต์ ๋ฉ๋ชจ๋ฆฌ, ์ค๋ ๋ ๋ก์ปฌ ๋ณ์๋ฅผ ๋๋ฒ๊น ํ์ต๋๋ค
- ์ค๋ ๋ ํ์ ํ์ต - ์์ฒ ๊ฐ์ ๋ณ๋ ฌ ์ค๋ ๋ ์ฌ์ด๋ฅผ ํจ์จ์ ์ผ๋ก ์ด๋ํ์ต๋๋ค
์ด๋ก ์์ ์ค์ ์ผ๋ก
GPU ๋๋ฒ๊น ์ ๋ํด ์ฝ๊ธฐ๋ง ํ ๊ฒ์ด ์๋๋ผ ๊ฒฝํํ์ต๋๋ค:
- ์ค์ ์ฝ๋ ๋๋ฒ๊น
: ์ค์ GPU ์คํ์ผ๋ก Puzzle 01์
add_10์ปค๋์ ๋๋ฒ๊น ํ์ต๋๋ค - ์ค์ ๋๋ฒ๊ฑฐ ์ถ๋ ฅ ํ์ธ: LLDB ์ด์ ๋ธ๋ฆฌ, CUDA-GDB ์ค๋ ๋ ์ํ, ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ง์ ํ์ธํ์ต๋๋ค
- ์ ๋ฌธ ๋๊ตฌ ์ฌ์ฉ: ํ๋ก๋์ GPU ๊ฐ๋ฐ์์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ CUDA-GDB๋ฅผ ์ฌ์ฉํ์ต๋๋ค
- ์ค์ ์๋๋ฆฌ์ค ํด๊ฒฐ: ๋ฒ์ ์ด๊ณผ ์ ๊ทผ, ๊ฒฝ์ ์ํ, ์ปค๋ ์คํ ์คํจ ๋ฌธ์ ๋ฅผ ๋ค๋ค์ต๋๋ค
๋๋ฒ๊น ๋๊ตฌ ๋ชจ์
๋น ๋ฅธ ๊ฒฐ์ ๊ฐ์ด๋ (ํญ์ ๊ฐ๊น์ด ๋์ธ์!):
| ๋ฌธ์ ์ ํ | ๋๊ตฌ | ๋ช ๋ น์ด |
|---|---|---|
| GPU ์ ์ ํ๋ก๊ทธ๋จ ํฌ๋์ | LLDB | pixi run mojo debug program.mojo |
| GPU ์ปค๋ ๋ฌธ์ | CUDA-GDB | pixi run mojo debug --cuda-gdb --break-on-launch program.mojo |
| ๊ฒฝ์ ์ํ | CUDA-GDB + ์ค๋ ๋ ํ์ | (cuda-gdb) cuda thread (0,0,0) |
ํ์ ๋ช ๋ น์ด (์ผ์ ๋๋ฒ๊น ์ฉ):
# GPU ์ค๋ ๋ ๊ฒ์ฌ
(cuda-gdb) info cuda threads # ๋ชจ๋ ์ค๋ ๋ ๋ณด๊ธฐ
(cuda-gdb) cuda thread (0,0,0) # ์ค๋ ๋ ์ ํ
(cuda-gdb) print i # ๋ก์ปฌ ์ค๋ ๋ ์ธ๋ฑ์ค (thread_idx.x ๋ฑ๊ฐ)
# ์ค๋งํธ ๋ธ๋ ์ดํฌํฌ์ธํธ (GPU ๋ด์ฅ ๋ณ์๊ฐ ์๋ํ์ง ์์ผ๋ฏ๋ก ๋ก์ปฌ ๋ณ์ ์ฌ์ฉ)
(cuda-gdb) break kernel if i == 0 # ์ค๋ ๋ 0์ ์ง์ค
(cuda-gdb) break kernel if array[i] > 100 # ๋ฐ์ดํฐ ์กฐ๊ฑด์ ์ง์ค
# ๋ฉ๋ชจ๋ฆฌ ๋๋ฒ๊น
(cuda-gdb) print array[i] # ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ค๋ ๋๋ณ ๋ฐ์ดํฐ
(cuda-gdb) print array[0]@4 # ๋ฐฐ์ด ์ธ๊ทธ๋จผํธ: {{val1}, {val2}, {val3}, {val4}}
์์ฝ
GPU ๋๋ฒ๊น ์๋ ์์ฒ ๊ฐ์ ๋ณ๋ ฌ ์ค๋ ๋, ๋ณต์กํ ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ, ์ ๋ฌธ ๋๊ตฌ๊ฐ ๊ด์ฌํฉ๋๋ค. ์ด์ ๋ค์์ ๊ฐ์ถ๊ฒ ๋์์ต๋๋ค:
- ์ด๋ค GPU ํ๋ก๊ทธ๋จ์๋ ์ ์ฉํ ์ ์๋ ์ฒด๊ณ์ ์ธ ์ํฌํ๋ก์ฐ
- LLDB์ CUDA-GDB ์ ๋ฌธ ๋๊ตฌ์ ๋ํ ์น์ํจ
- ์ค์ ๋ณ๋ ฌ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ ์ค์ ๊ฒฝํ
- ๋ณต์กํ ์ํฉ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ค์ฉ์ ์ธ ์ ๋ต
- GPU ๋๋ฒ๊น ๊ณผ์ ๋ฅผ ํด๊ฒฐํ ๊ธฐ์ด
์ถ๊ฐ ์๋ฃ
- Mojo ๋๋ฒ๊น ๋ฌธ์
- Mojo GPU ๋๋ฒ๊น ๊ฐ์ด๋
- NVIDIA CUDA-GDB ์ฌ์ฉ์ ๊ฐ์ด๋
- CUDA-GDB ๋ช ๋ น์ด ์ฐธ์กฐ
์ฐธ๊ณ : GPU ๋๋ฒ๊น ์๋ ์ธ๋ด์ฌ๊ณผ ์ฒด๊ณ์ ์ธ ์กฐ์ฌ๊ฐ ํ์ํฉ๋๋ค. ์ด ํผ์ฆ์์ ๋ค๋ฃฌ ์ํฌํ๋ก์ฐ์ ๋ช ๋ น์ด๋ ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ง์ฃผ์น๊ฒ ๋ ๋ณต์กํ GPU ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๋ ๊ธฐ์ด๊ฐ ๋ฉ๋๋ค.