π 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. μμ€ + LLDB: μμ€μμ μ§μ CPU νΈμ€νΈ μ½λ λλ²κΉ
pixi run mojo debug your_gpu_program.mojo
# 2. μμ€ + 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
κ° μ κ·Όλ²μ μΈμ μ¬μ©ν κΉ
νμ΅κ³Ό λΉ λ₯Έ μ€νμ©:
- μμ€ λλ²κΉ μ¬μ© - λ³λ λΉλ λ¨κ³κ° νμ μμ΄ λ λΉ λ₯΄κ² λ°λ³΅ κ°λ₯
본격μ μΈ λλ²κΉ μΈμ μ©:
- λ°μ΄λ리 λλ²κΉ
μ¬μ© - λ μμΈ‘ κ°λ₯νκ³ κΉλν λλ²κ±° μΆλ ₯, λΉλ
νλκ·Έλ₯Ό μμ ν μ μ΄ κ°λ₯ (
-O0 -gλ‘ λ‘컬 λ³μ 보쑴)
CPU μΈ‘ λ¬Έμ μ© (λ²νΌ ν λΉ, νΈμ€νΈ λ©λͺ¨λ¦¬, νλ‘κ·Έλ¨ λ‘μ§):
- LLDB λͺ¨λ μ¬μ© -
main()ν¨μμ μ€μ μ½λ λλ²κΉ μ μ ν©
GPU 컀λ λ¬Έμ μ© (μ€λ λ λμ, GPU λ©λͺ¨λ¦¬, 컀λ ν¬λμ):
- CUDA-GDB λͺ¨λ μ¬μ© - κ°λ³ GPU μ€λ λλ₯Ό κ²μ¬νλ μ μΌν λ°©λ²
μ₯μ μ λ€μνκ² μ‘°ν©ν΄μ μ¬μ©ν μ μλ€λ μ μ λλ€. μμ€ + LLDBλ‘ μ€μ μ½λλ₯Ό λλ²κΉ ν λ€μ, μμ€ + 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μ μμ λ‘ λ€ κ°μ§ λλ²κΉ μ‘°ν©μ νμν©λλ€. νμ΅ κ²½λ‘: μμ€ + LLDB(κ°μ₯ μ¬μ)λ‘ μμν΄μ CUDA-GDB(κ°μ₯ κ°λ ₯ν¨)λ‘ μ§νν©λλ€.
β οΈ GPU λλ²κΉ μ μ€μμ¬ν:
--break-on-launchνλκ·Έλ CUDA-GDB μ κ·Όλ²μμ νμ- 미리 μ»΄νμΌλ λ°μ΄λ리 (μ κ·Όλ² 3 & 4)λ
-O0 -gλ‘ λΉλλμ΄ μ΅μ νκ° λΉνμ±νλκ³ λλ²κ·Έ μ¬λ³Όμ΄ ν¬ν¨λ©λλ€ β κ·Έλμiκ°μ λ‘컬 λ³μκ° κ²μ¬λ₯Ό μν΄ λ³΄μ‘΄λ©λλ€ - μμ€μμ λλ²κΉ (μ κ·Όλ² 1 & 2)μ κΈ°λ³Έ νλκ·Έλ‘ μ»΄νμΌλλ―λ‘, λλΆλΆμ λ‘컬 λ³μκ° μ΅μ νλ‘ μ κ±°λ©λλ€
- 본격μ μΈ GPU λλ²κΉ μλ μ κ·Όλ² 4 (λ°μ΄λ리 + CUDA-GDB) μ¬μ©
νν λ¦¬μΌ Step 1: LLDBλ‘ CPU λλ²κΉ
κ°μ₯ μΌλ°μ μΈ λλ²κΉ
μλ리μ€λ‘ μμν©μλ€: νλ‘κ·Έλ¨μ΄ ν¬λμνκ±°λ μμμΉ
λͺ»ν λμμ ν΄μ main() ν¨μμμ λ¬΄μ¨ μΌμ΄ μΌμ΄λλμ§ λ΄μΌ ν λ.
λ―Έμ : Puzzle 01μ CPU μΈ‘ μ€μ μ½λλ₯Ό λλ²κΉ νμ¬ Mojoκ° GPU λ©λͺ¨λ¦¬λ₯Ό μ΄κΈ°ννκ³ μ»€λμ μ€ννλ λ°©λ²μ νμ ν©λλ€.
λλ²κ±° μ€ν
μμ€μμ μ§μ 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: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
μ΄κ²μ μμλλ λμμ
λλ€. mojo debug your_program.mojoλ‘ μ€ννλ©΄ λλ²κ·Έ
μΈμ
μ΄ μμλ λ νλ‘κ·Έλ¨μ΄ μ»΄νμΌλλ―λ‘, λΈλ μ΄ν¬ν¬μΈνΈλ₯Ό μ€μ νλ μμ μλ
λͺ¨λμ΄ μμ§ λλ²κ±°μ λ‘λλμ§ μμμ΅λλ€. LLDBλ λΈλ μ΄ν¬ν¬μΈνΈλ₯Ό 보λ₯ μνλ‘
λ±λ‘νλ©° μμ§ κ΅¬μ²΄μ μΈ λͺ
λ Ήμ΄ μ£Όμμ λ°μΈλ©ν μ μμ΅λλ€. μ€νμ΄ μμλκ³
λͺ¨λμ΄ λ‘λλλ©΄ LLDBκ° μλμΌλ‘ λΈλ μ΄ν¬ν¬μΈνΈλ₯Ό ν΄κ²°ν©λλ€.
Step 2: νλ‘κ·Έλ¨ μμ
(lldb) run
μΆλ ₯:
Process 186951 launched: '/home/ubuntu/workspace/mojo-gpu-puzzles/.pixi/envs/default/bin/mojo' (x86_64)
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.2
frame #0: 0x00007fff5c01e841 JIT(0x7fff5c075000)`std::builtin::_startup::__mojo_main_prototype(argc=1, argv=0x00007fffffffa858) at _startup.mojo:119:5
νλ‘κ·Έλ¨μ΄ μμλλ©΄ 보λ₯ μ€μ΄λ λΈλ μ΄ν¬ν¬μΈνΈκ° 2κ°μ μμΉλ‘ ν΄κ²°λ©λλ€ β
νλλ _startup.mojo(Mojoμ λ΄λΆ μμ λνΌ)μ, λ€λ₯Έ νλλ μ¬λ¬λΆμ
p01.mojoμ mainμ μμΉν©λλ€. LLDBλ 첫 λ²μ§Έ ννΈμΈ μμ λνΌμμ λ©μΆ₯λλ€.
SIGCHLD μκ·Έλμ μ μμ
λλ€ β Mojoκ° λ΄λΆ νλ‘μΈμ€λ₯Ό κ΄λ¦¬νλ λ°©μμ
λλ€.
Step 3: μ€μ μ½λλ‘ κ³μ
# p01.mojo μ½λμ λλ¬νκΈ° μν΄ continue
(lldb) continue
μΆλ ₯:
Process 186951 resuming
Process 186951 stopped
* thread #1, name = 'mojo', stop reason = breakpoint 1.1
frame #0: 0x00007fff5c014040 JIT(0x7fff5c075000)`p01::main() at p01.mojo:30:23
27
28
29 def main() raises:
-> 30 with DeviceContext() as ctx:
31 var out = ctx.enqueue_create_buffer[dtype](SIZE)
32 out.enqueue_fill(0)
33 var a = ctx.enqueue_create_buffer[dtype](SIZE)
μ΄μ μ€μ Mojo μμ€ μ½λλ₯Ό λ³Ό μ μμ΅λλ€. μ£Όλͺ©ν μ :
- p01.mojo νμΌμ 27-33λ² μ€
- νμ¬ μ€ 30:
with DeviceContext() as ctx: - μΈνλ‘μΈμ€ μ€ν:
JIT(0x7fff5c075000)μ λμ¬λ μ€ν μ€μΈ νλ‘μΈμ€μ λ‘λλ μ½λ μμμ λν LLDBμ λΌλ²¨μ λλ€.mojo debug your_program.mojoλ‘ μ€ννλ©΄, μ»΄νμΌλ νλ‘κ·Έλ¨μ΄ λμ€ν¬μ μ€ν νμΌμ μ°μ§ μκ³ μΈνλ‘μΈμ€μμ μ€νλ©λλ€ β κ·Έλμ μ΄ κ²½λ‘κ° λ¨Όμ λ°μ΄λ리λ₯Ό λΉλνλ κ²λ³΄λ€ μμμ΄ λΉ λ₯΄κ³ ,your_program_debugνμΌμ΄ μμ±λμ§ μμ΅λλ€
Step 4: νλ‘κ·Έλ¨ μλ£
# νλ‘κ·Έλ¨μ μλ£κΉμ§ μ€ν
(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μ λ΄λΆ μ΄κΈ°ν μ½λκ° μμμ νμ΅ (λΈλ μ΄ν¬
ν¬μΈνΈκ° λ μμΉλ‘ ν΄κ²°λμ΄ λ¨Όμ
_startup.mojoμμ λ©μ·μ΅λλ€) - μμ€ μ½λ λλ¬ - ꡬ문 κ°μ‘°κ° λ μ€μ p01.mojo 27-33λ² μ€ νμΈ
- μΈνλ‘μΈμ€ μ€ν κ΄μ°° -
mojo debug your_program.mojoκ° νλ‘κ·Έλ¨μ μ»΄νμΌνκ³ λμ€ν¬μ μ€ν νμΌμ μ°μ§ μκ³ λ°λ‘ μ€ννλ κ²μ κ΄μ°° - μ±κ³΅μ μΈ μ€ν νμΈ - νλ‘κ·Έλ¨μ΄ μμλ μΆλ ₯μ μμ±ν¨μ νμΈ
LLDB λλ²κΉ μ΄ μ 곡νλ κ²:
- β
CPU μΈ‘ κ°μμ±:
main()ν¨μ, λ²νΌ ν λΉ, λ©λͺ¨λ¦¬ μ€μ νμΈ - β μμ€ μ½λ κ²μ¬: μ€ λ²νΈκ° μλ μ€μ Mojo μ½λ 보기
- β λ³μ κ²μ¬: νΈμ€νΈ μΈ‘ λ³μ(CPU λ©λͺ¨λ¦¬) κ° νμΈ
- β νλ‘κ·Έλ¨ νλ¦ μ μ΄: μ€μ λ‘μ§μ μ€ λ¨μλ‘ λ¨κ³λ³ μ€ν
- β μ€λ₯ μ‘°μ¬: μ₯μΉ μ€μ , λ©λͺ¨λ¦¬ ν λΉ λ±μ ν¬λμ λλ²κΉ
LLDBκ° ν μ μλ κ²:
- β GPU 컀λ κ²μ¬:
add_10ν¨μ μ€ν λ΄λΆλ‘ μ§μ λΆκ°λ₯ - β μ€λ λ μμ€ λλ²κΉ : κ°λ³ GPU μ€λ λ λμ νμΈ λΆκ°
- β GPU λ©λͺ¨λ¦¬ μ κ·Ό: GPU μ€λ λκ° λ³΄λ λ°μ΄ν° κ²μ¬ λΆκ°
- β λ³λ ¬ μ€ν λΆμ: κ²½μ μνλ λκΈ°ν λλ²κΉ λΆκ°
LLDB λλ²κΉ μ μ¬μ©ν λ:
- GPU μ½λκ° μ€νλκΈ° μ μ νλ‘κ·Έλ¨μ΄ ν¬λμν λ
- λ²νΌ ν λΉμ΄λ λ©λͺ¨λ¦¬ μ€μ λ¬Έμ
- νλ‘κ·Έλ¨ μ΄κΈ°νμ νλ¦ μ΄ν΄
- Mojo μ ν리μΌμ΄μ μ΄ μ΄λ»κ² μμλλμ§ νμ΅
- λΉ λ₯Έ νλ‘ν νμ΄νκ³Ό μ½λ λ³κ²½ μ€ν
ν΅μ¬ ν΅μ°°: LLDBλ νΈμ€νΈ μΈ‘ λλ²κΉ μ μλ²½ν©λλ€ - GPU μ€ν μ νμ CPUμμ μΌμ΄λλ λͺ¨λ κ². μ€μ GPU 컀λ λλ²κΉ μλ λ€μ μ κ·Όλ²μ΄ νμν©λλ€β¦
νν λ¦¬μΌ Step 2: λ°μ΄λ리 λλ²κΉ
μμ€ λλ²κΉ μ λ°°μ μΌλ μ΄μ νλ‘λμ νκ²½μμ μ¬μ©νλ μ λ¬Έμ μΈ μ κ·Όλ²μ νμν©μλ€.
μλ리μ€: μ¬λ¬ νμΌμ΄ μλ 볡μ‘ν μ ν리μΌμ΄μ μ λλ²κΉ νκ±°λ κ°μ νλ‘κ·Έλ¨μ λ°λ³΅μ μΌλ‘ λλ²κΉ ν΄μΌ ν©λλ€. λ¨Όμ λ°μ΄λ리λ₯Ό λΉλνλ©΄ λ λ§μ μ μ΄μ λΉ λ₯Έ λλ²κΉ λ°λ³΅μ΄ κ°λ₯ν©λλ€.
λλ²κ·Έ λ°μ΄λ리 λΉλ
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
무μμ΄ λ€λ₯Έκ° (κ·Έλ¦¬κ³ λ λμκ°)
μμ λΉκ΅:
| μμ€ λλ²κΉ | λ°μ΄λ리 λλ²κΉ |
|---|---|
| ν λ¨κ³λ‘ μ»΄νμΌ + λλ²κΉ | ν λ² λΉλ, μ¬λ¬ λ² λλ²κΉ |
| λλ¦° μμ (μ»΄νμΌ μ€λ²ν€λ) | λΉ λ₯Έ μμ |
| μ»΄νμΌ λ©μμ§κ° λλ²κ·Έ μΆλ ₯κ³Ό μμ | κΉλν λλ²κ±° μΆλ ₯ |
| κΈ°λ³Έ λΉλ νλκ·Έ | λͺ
μμ -O0 -g λΉλ νλκ·Έ |
κ°μ LLDB λͺ
λ Ήμ΄(br set -n main, run, continue)λ₯Ό μ€ννλ©΄ λ€μκ³Ό κ°μ
μ°¨μ΄λ₯Ό λλ μ μμ΅λλ€:
- λΉ λ₯Έ μμ - μ»΄νμΌ μ§μ° μμ
- κΉλν μΆλ ₯ - μ»΄νμΌ λ©μμ§κ° μμ΄μ§ μμ
- λ μμΈ‘ κ°λ₯ - λΉλ νλκ·Έκ° λͺ μμ μ΄κ³ μ€ν κ°μ μ¬μ¬μ©λ¨
- μ λ¬Έμ μΈ μν¬νλ‘μ° - νλ‘λμ λλ²κΉ μ΄ μ΄λ κ² μλν¨
νν λ¦¬μΌ 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
# μμ€ + CUDA-GDB μ¬μ© (μμ μ κ·Όλ² 2)
pixi run mojo debug --cuda-gdb --break-on-launch solutions/p01/p01.mojo
νμ΅κ³Ό λΉ λ₯Έ λ°λ³΅μ μ ν©ν μμ€ + 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 = (!kgen.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 = (!kgen.scalar<f32> * @register) 0x302000200
(cuda-gdb) print output # μΆλ ₯ λ°°μ΄ GPU ν¬μΈν°
μΆλ ₯:
$10 = (!kgen.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 λ©λͺ¨λ¦¬, κ²½μ μν λλ²κΉ
- β μμ€ vs λ°μ΄λ리 λλ²κΉ - μν©μ λ§λ μ κ·Όλ² μ ν
- β pixiλ‘ νκ²½ κ΄λ¦¬ - μΌκ΄λκ³ μ λ’°ν μ μλ λλ²κΉ μ€μ 보μ₯
μ€μ λ³λ ¬ νλ‘κ·Έλλ° ν΅μ°°:
- μ€λ λμ μ€μ λμ νμΈ - λ³λ ¬ μ€λ λλ§λ€
thread_idx.xκ° λ€λ₯Έ κ°μ κ°λ κ²μ μ§μ λͺ©κ²©νμ΅λλ€ - λ©λͺ¨λ¦¬ κ³μΈ΅ ꡬ쑰 μ΄ν΄ - μ μ GPU λ©λͺ¨λ¦¬, 곡μ λ©λͺ¨λ¦¬, μ€λ λ λ‘컬 λ³μλ₯Ό λλ²κΉ νμ΅λλ€
- μ€λ λ νμ νμ΅ - μμ² κ°μ λ³λ ¬ μ€λ λ μ¬μ΄λ₯Ό ν¨μ¨μ μΌλ‘ μ΄λνμ΅λλ€
μ΄λ‘ μμ μ€μ μΌλ‘
GPU λλ²κΉ μ λν΄ μ½κΈ°λ§ ν κ²μ΄ μλλΌ κ²½ννμ΅λλ€:
- μ€μ μ½λ λλ²κΉ
: μ€μ GPU μ€νμΌλ‘ Puzzle 01μ
add_10컀λμ λλ²κΉ νμ΅λλ€ - μ€μ λλ²κ±° μΆλ ₯ νμΈ: JIT λΌλ²¨μ΄ λΆμ νλ μμμ 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 λ¬Έμ λ₯Ό λλ²κΉ νλ κΈ°μ΄κ° λ©λλ€.