๐Ÿ“š 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 ํ”„๋กœ๊ทธ๋žจ์ด ํฌ๋ž˜์‹œํ•˜๊ฑฐ๋‚˜, ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๊ฑฐ๋‚˜, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์„ ํ•  ๋•Œ ๋‹ค์Œ์˜ ์ฒด๊ณ„์ ์ธ ์ ‘๊ทผ๋ฒ•์„ ๋”ฐ๋ฅด์„ธ์š”:

  1. ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ์ฝ”๋“œ ์ค€๋น„ (์ตœ์ ํ™” ๋น„ํ™œ์„ฑํ™”, ๋””๋ฒ„๊ทธ ์‹ฌ๋ณผ ์ถ”๊ฐ€)
  2. ์ ์ ˆํ•œ ๋””๋ฒ„๊ฑฐ ์„ ํƒ (CPU ํ˜ธ์ŠคํŠธ ์ฝ”๋“œ vs GPU ์ปค๋„ ๋””๋ฒ„๊น…)
  3. ์ „๋žต์  ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ ์„ค์ • (๋ฌธ์ œ๊ฐ€ ์˜์‹ฌ๋˜๋Š” ์œ„์น˜์—)
  4. ์‹คํ–‰ ๋ฐ ๊ฒ€์‚ฌ (์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ์‹คํ–‰ํ•˜๋ฉฐ ๋ณ€์ˆ˜ ๊ฒ€์‚ฌ)
  5. ํŒจํ„ด ๋ถ„์„ (๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ, ์Šค๋ ˆ๋“œ ๋™์ž‘, ๊ฒฝ์Ÿ ์ƒํƒœ)

์ด ์›Œํฌํ”Œ๋กœ์šฐ๋Š” 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 ํ”„๋กœ๊ทธ๋žจ ๋””๋ฒ„๊น… ์„ธ์…˜์„ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:

๊ฑฐ์ณ์˜จ ๋””๋ฒ„๊น… ์—ฌ์ •:

  1. ์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ์‹œ์ž‘ - ์ €์ˆ˜์ค€ ๋””๋ฒ„๊น…์—์„œ๋Š” ์ •์ƒ์ ์ธ ํ˜„์ƒ์ด๋ฉฐ, ๋””๋ฒ„๊ฑฐ๊ฐ€ ๋จธ์‹  ์ˆ˜์ค€์—์„œ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ณด์—ฌ์คŒ
  2. Mojo ์‹œ์ž‘ ๊ณผ์ • ํƒ์ƒ‰ - Mojo์— ๋‚ด๋ถ€ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๊ฐ€ ์žˆ์Œ์„ ํ•™์Šต
  3. ์†Œ์Šค ์ฝ”๋“œ ๋„๋‹ฌ - ๊ตฌ๋ฌธ ๊ฐ•์กฐ๊ฐ€ ๋œ ์‹ค์ œ p01.mojo 21-27๋ฒˆ ์ค„ ํ™•์ธ
  4. JIT ์ปดํŒŒ์ผ ๊ด€์ฐฐ - Mojo๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ฆ‰์„์—์„œ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฒƒ์„ ๊ด€์ฐฐ
  5. ์„ฑ๊ณต์ ์ธ ์‹คํ–‰ ํ™•์ธ - ํ”„๋กœ๊ทธ๋žจ์ด ์˜ˆ์ƒ๋œ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•จ์„ ํ™•์ธ

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=0 vs i=1, a[i]={0} vs a[i]={1}, output[i]={10} vs output[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 ๋””๋ฒ„๊น… ํŠœํ† ๋ฆฌ์–ผ์„ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณ‘๋ ฌ ์ปดํ“จํŒ…์— ๋Œ€ํ•ด ๋ฐœ๊ฒฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค:

๋ณ‘๋ ฌ ์‹คํ–‰์— ๋Œ€ํ•œ ๊นŠ์€ ํ†ต์ฐฐ

  1. ์Šค๋ ˆ๋“œ ์ธ๋ฑ์‹ฑ์˜ ์‹ค์ œ: thread_idx.x๊ฐ€ ๋ณ‘๋ ฌ ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’(0, 1, 2, 3โ€ฆ)์„ ๊ฐ–๋Š” ๊ฒƒ์„ ์ด๋ก ์ด ์•„๋‹Œ ์ง์ ‘ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค

  2. ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ํŒจํ„ด ํŒŒ์•…: ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ a[thread_idx.x]์—์„œ ์ฝ๊ณ  output[thread_idx.x]์— ์“ฐ๋ฉฐ, ์ถฉ๋Œ ์—†์ด ์™„๋ฒฝํ•œ ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ์„ฑ์„ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค

  3. ๋ณ‘๋ ฌ ์‹คํ–‰์˜ ์ดํ•ด: ์ˆ˜์ฒœ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์ผํ•œ ์ปค๋„ ์ฝ”๋“œ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋ฉด์„œ ๊ฐ๊ฐ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค

  4. GPU ๋ฉ”๋ชจ๋ฆฌ ๊ณ„์ธต ๊ตฌ์กฐ: ๋ฐฐ์—ด์€ ์ „์—ญ GPU ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ์–ด ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์Šค๋ ˆ๋“œ๋ณ„ ์ธ๋ฑ์‹ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

๋ชจ๋“  ํผ์ฆ์— ์ ์šฉ๋˜๋Š” ๋””๋ฒ„๊น… ๊ธฐ๋ฒ•

Puzzle 01๋ถ€ํ„ฐ Puzzle 08, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ดํ›„๊นŒ์ง€ ๋ณดํŽธ์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ๊ธฐ๋ฒ•์„ ์Šต๋“ํ–ˆ์Šต๋‹ˆ๋‹ค:

  • CPU ์ธก ๋ฌธ์ œ(์žฅ์น˜ ์„ค์ •, ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น)๋Š” LLDB๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค
  • GPU ์ปค๋„ ๋ฌธ์ œ(์Šค๋ ˆ๋“œ ๋™์ž‘, ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ)๋Š” CUDA-GDB๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • ํŠน์ • ์Šค๋ ˆ๋“œ๋‚˜ ๋ฐ์ดํ„ฐ ์กฐ๊ฑด์— ์ง‘์ค‘ํ•˜๋ ค๋ฉด ์กฐ๊ฑด๋ถ€ ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
  • ๋ณ‘๋ ฌ ์‹คํ–‰ ํŒจํ„ด์„ ์ดํ•ดํ•˜๋ ค๋ฉด ์Šค๋ ˆ๋“œ ๊ฐ„ ์ด๋™์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค
  • ๊ฒฝ์Ÿ ์ƒํƒœ์™€ ๋ฒ”์œ„ ์ดˆ๊ณผ ์˜ค๋ฅ˜๋ฅผ ์žก์œผ๋ ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ํŒจํ„ด์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค

ํ™•์žฅ์„ฑ: ์ด ๊ธฐ๋ฒ•๋“ค์€ ๋‹ค์Œ ๋ชจ๋“  ์ƒํ™ฉ์—์„œ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

  • Puzzle 01: ๊ฐ„๋‹จํ•œ ๋ง์…ˆ์„ ํ•˜๋Š” 4๊ฐœ ์š”์†Œ ๋ฐฐ์—ด
  • Puzzle 08: ์Šค๋ ˆ๋“œ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๋ณต์žกํ•œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ์—ฐ์‚ฐ
  • ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ: ์ •๊ตํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฑ๋งŒ ๊ฐœ ์š”์†Œ ๋ฐฐ์—ด

ํ•„์ˆ˜ ๋””๋ฒ„๊น… ๋ช…๋ น์–ด ์ฐธ์กฐ

๋””๋ฒ„๊น… ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋ฐฐ์› ์œผ๋‹ˆ, ์ผ์ƒ์ ์ธ ๋””๋ฒ„๊น… ์„ธ์…˜์—์„œ ์“ธ ๋น ๋ฅธ ์ฐธ์กฐ ๊ฐ€์ด๋“œ๋ฅผ ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ด ์„น์…˜์„ ๋ถ๋งˆํฌํ•˜์„ธ์š”!

GDB ๋ช…๋ น์–ด ์•ฝ์–ด (์‹œ๊ฐ„ ์ ˆ์•ฝ!)

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋‹จ์ถ•ํ‚ค๋กœ ๋” ๋น ๋ฅธ ๋””๋ฒ„๊น…:

์•ฝ์–ด์ „์ฒด ๋ช…๋ น์–ด๊ธฐ๋Šฅ
rrunํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘/์‹คํ–‰
ccontinue์‹คํ–‰ ์žฌ๊ฐœ
nnext์Šคํ… ์˜ค๋ฒ„ (๊ฐ™์€ ๋ ˆ๋ฒจ)
sstepํ•จ์ˆ˜ ๋‚ด๋ถ€๋กœ ์ง„์ž…
bbreak๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ ์„ค์ •
pprint๋ณ€์ˆ˜ ๊ฐ’ ์ถœ๋ ฅ
llist์†Œ์Šค ์ฝ”๋“œ ํ‘œ์‹œ
qquit๋””๋ฒ„๊ฑฐ ์ข…๋ฃŒ

์˜ˆ์‹œ:

(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 ์ „์— ํ”„๋กœ๊ทธ๋žจ ํฌ๋ž˜์‹œLLDBpixi run mojo debug program.mojo
GPU ์ปค๋„ ๋ฌธ์ œCUDA-GDBpixi 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 ๋””๋ฒ„๊น… ๊ณผ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ธฐ์ดˆ

์ถ”๊ฐ€ ์ž๋ฃŒ

์ฐธ๊ณ : GPU ๋””๋ฒ„๊น…์—๋Š” ์ธ๋‚ด์‹ฌ๊ณผ ์ฒด๊ณ„์ ์ธ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ํผ์ฆ์—์„œ ๋‹ค๋ฃฌ ์›Œํฌํ”Œ๋กœ์šฐ์™€ ๋ช…๋ น์–ด๋Š” ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋งˆ์ฃผ์น˜๊ฒŒ ๋  ๋ณต์žกํ•œ GPU ๋ฌธ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๊ธฐ์ดˆ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.