Puzzle 25: ์ํ ํต์
๊ฐ์
Puzzle 25: ์ํ ํต์ ๊ธฐ๋ณธ ์์์์๋ ๊ณ ๊ธ GPU ์ํ ๋ ๋ฒจ ํต์ ์ฐ์ฐ - ์ํ ๋ด์์ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ๊ตํ๊ณผ ์กฐ์ ํจํด์ ๊ฐ๋ฅํ๊ฒ ํ๋ ํ๋์จ์ด ๊ฐ์ ๊ธฐ๋ณธ ์์๋ฅผ ์๊ฐํฉ๋๋ค. shuffle_down๊ณผ broadcast๋ฅผ ์ฌ์ฉํ์ฌ ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํจํด ์์ด ์ด์ ํต์ ๊ณผ ์งํฉ ์กฐ์ ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค.
Part VII: GPU ์ํ ํต์ ์์๋ ์ค๋ ๋ ๊ทธ๋ฃน ๋ด ์ํ ๋ ๋ฒจ ๋ฐ์ดํฐ ์ด๋ ์ฐ์ฐ์ ๋ค๋ฃน๋๋ค. ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ + ์ธ๋ฑ์ฑ + ๊ฒฝ๊ณ ๊ฒ์ฌ ํจํด์ ํ๋์จ์ด ์ต์ ํ๋ ๋ฐ์ดํฐ ์ด๋์ ํ์ฉํ๋ ํจ์จ์ ์ธ ์ํ ํต์ ํธ์ถ๋ก ๋์ฒดํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค.
ํต์ฌ ํต์ฐฐ: GPU ์ํ๋ ๋ก์คํ ์ผ๋ก ์คํ๋ฉ๋๋ค - Mojo์ ์ํ ํต์ ์ฐ์ฐ์ ์ด ๋๊ธฐํ๋ฅผ ํ์ฉํ์ฌ ์๋ ๊ฒฝ๊ณ ์ฒ๋ฆฌ์ ๋ช ์์ ๋๊ธฐํ ์์ด ํจ์จ์ ์ธ ๋ฐ์ดํฐ ๊ตํ ๊ธฐ๋ณธ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
๋ฐฐ์ธ ๋ด์ฉ
์ํ ํต์ ๋ชจ๋ธ
GPU ์ํ ๋ด ๊ธฐ๋ณธ ํต์ ํจํด์ ์ดํดํฉ๋๋ค:
GPU ์ํ (32 ์ค๋ ๋, SIMT ๋ก์คํ
์คํ)
โโโ ๋ ์ธ 0 โโshuffle_downโโ> ๋ ์ธ 1 โโshuffle_downโโ> ๋ ์ธ 2
โโโ ๋ ์ธ 1 โโshuffle_downโโ> ๋ ์ธ 2 โโshuffle_downโโ> ๋ ์ธ 3
โโโ ๋ ์ธ 2 โโshuffle_downโโ> ๋ ์ธ 3 โโshuffle_downโโ> ๋ ์ธ 4
โ ...
โโโ ๋ ์ธ 31 โโshuffle_downโโ> undefined (๊ฒฝ๊ณ)
๋ธ๋ก๋์บ์คํธ ํจํด:
๋ ์ธ 0 โโbroadcastโโ> ๋ชจ๋ ๋ ์ธ (0, 1, 2, ..., 31)
ํ๋์จ์ด ํ์ค:
- ๋ ์ง์คํฐ ๊ฐ ์ง์ ํต์ : ๋ฐ์ดํฐ๊ฐ ์ค๋ ๋ ๋ ์ง์คํฐ ์ฌ์ด๋ฅผ ์ง์ ์ด๋ํฉ๋๋ค
- ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋ ์ ๋ก: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ํ์ํ์ง ์์ต๋๋ค
- ์๋ ๊ฒฝ๊ณ ์ฒ๋ฆฌ: ํ๋์จ์ด๊ฐ ์ํ ๊ฒฝ๊ณ์ ์์ธ ์ํฉ์ ๊ด๋ฆฌํฉ๋๋ค
- ๋จ์ผ ์ฌ์ดํด ์ฐ์ฐ: ํ๋์ ๋ช ๋ น ์ฌ์ดํด์์ ํต์ ์ด ์๋ฃ๋ฉ๋๋ค
Mojo์ ์ํ ํต์ ์ฐ์ฐ
gpu.primitives.warp์ ํต์ฌ ํต์ ๊ธฐ๋ณธ ์์๋ฅผ ๋ฐฐ์๋๋ค:
shuffle_down(value, offset): ๋ ๋์ ์ธ๋ฑ์ค์ ๋ ์ธ์์ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ (์ด์ ์ ๊ทผ)broadcast(value): ๋ ์ธ 0์ ๊ฐ์ ๋ชจ๋ ๋ ์ธ์ ๊ณต์ (์ผ๋๋ค)shuffle_idx(value, lane): ํน์ ๋ ์ธ์์ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ (์์ ์ ๊ทผ)shuffle_up(value, offset): ๋ ๋ฎ์ ์ธ๋ฑ์ค์ ๋ ์ธ์์ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ (์ญ๋ฐฉํฅ ์ด์)
์ฐธ๊ณ : ์ด ํผ์ฆ์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํต์ ํจํด์ธ
shuffle_down()๊ณผbroadcast()์ ์ด์ ์ ๋ง์ถฅ๋๋ค. ๋ชจ๋ ์ํ ์ฐ์ฐ์ ๋ํ ์ ์ฒด ๋ด์ฉ์ Mojo GPU ์ํ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ฑ๋ฅ ๋ณํ ์์
# ๋ณต์กํ ์ด์ ์ ๊ทผ ํจํด (๊ธฐ์กด ๋ฐฉ์):
shared = LayoutTensor[
dtype,
Layout.row_major(WARP_SIZE),
MutAnyOrigin,
address_space = AddressSpace.SHARED,
].stack_allocation()
shared[local_i] = input[global_i]
barrier()
if local_i < WARP_SIZE - 1:
next_value = shared[local_i + 1] # ์ด์ ์ ๊ทผ
result = next_value - shared[local_i]
else:
result = 0 # ๊ฒฝ๊ณ ์ฒ๋ฆฌ
barrier()
# ์ํ ํต์ ์ ์ด ๋ชจ๋ ๋ณต์ก์ฑ์ ์ ๊ฑฐํฉ๋๋ค:
current_val = input[global_i]
next_val = shuffle_down(current_val, 1) # ์ด์์ ์ง์ ์ ๊ทผ
if lane < WARP_SIZE - 1:
result = next_val - current_val
else:
result = 0
์ํ ํต์ ์ด ๋น๋๋ ์๊ฐ
์ฑ๋ฅ ํน์ฑ์ ์ดํดํฉ๋๋ค:
| ํต์ ํจํด | ๊ธฐ์กด ๋ฐฉ์ | ์ํ ์ฐ์ฐ |
|---|---|---|
| ์ด์ ์ ๊ทผ | ๊ณต์ ๋ฉ๋ชจ๋ฆฌ | ๋ ์ง์คํฐ ๊ฐ ์ง์ ํต์ |
| ์คํ ์ค ์ฐ์ฐ | ๋ณต์กํ ์ธ๋ฑ์ฑ | ๊ฐ๋จํ ์ ํ ํจํด |
| ๋ธ๋ก ์กฐ์ | ๋ฐฐ๋ฆฌ์ด + ๊ณต์ ๋ฉ๋ชจ๋ฆฌ | ๋จ์ผ ๋ธ๋ก๋์บ์คํธ |
| ๊ฒฝ๊ณ ์ฒ๋ฆฌ | ์๋ ๊ฒ์ฌ | ํ๋์จ์ด ์๋ ์ฒ๋ฆฌ |
์ ์ ์ง์
์ํ ํต์ ์ ๋ค์ด๊ฐ๊ธฐ ์ ์ ๋ค์ ๋ด์ฉ์ ์ต์ํด์ผ ํฉ๋๋ค:
- Part VII ์ํ ๊ธฐ์ด: SIMT ์คํ๊ณผ ๊ธฐ๋ณธ ์ํ ์ฐ์ฐ์ ๋ํ ์ดํด (Puzzle 24: ์ํ ๊ธฐ์ด ์ฐธ๊ณ )
- GPU ์ค๋ ๋ ๊ณ์ธต ๊ตฌ์กฐ: ๋ธ๋ก, ์ํ, ๋ ์ธ ๋ฒํธ ๋งค๊ธฐ๊ธฐ
- LayoutTensor ์ฐ์ฐ: ๋ก๋, ์ ์ฅ, ํ ์ ์กฐ์
- ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒ๋ฆฌ: ๋ณ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ฅ์๋ฆฌ ์ผ์ด์ค ๊ด๋ฆฌ
ํ์ต ๊ฒฝ๋ก
1. shuffle_down์ ์ด์ฉํ ์ด์ ํต์
์คํ ์ค ์ฐ์ฐ๊ณผ ์ ํ ์ฐจ๋ถ์ ์ํ ์ด์ ๊ธฐ๋ฐ ํต์ ํจํด์ ๋ฐฐ์๋๋ค.
๋ฐฐ์ธ ๋ด์ฉ:
shuffle_down()์ผ๋ก ์ธ์ ๋ ์ธ ๋ฐ์ดํฐ ์ ๊ทผํ๊ธฐ- ์ ํ ์ฐจ๋ถ๊ณผ ์ด๋ ํ๊ท ๊ตฌํ
- ์ํ ๊ฒฝ๊ณ ์๋ ์ฒ๋ฆฌ
- ํ์ฅ๋ ์ด์ ์ ๊ทผ์ ์ํ ๋ค์ค ์คํ์ ์ ํ
ํต์ฌ ํจํด:
current_val = input[global_i]
next_val = shuffle_down(current_val, 1)
if lane < WARP_SIZE - 1:
result = compute_with_neighbors(current_val, next_val)
2. ๋ธ๋ก๋์บ์คํธ๋ฅผ ์ด์ฉํ ์งํฉ ์กฐ์
โ warp.broadcast()
๋ธ๋ก ๋ ๋ฒจ ์กฐ์ ๊ณผ ์งํฉ์ ์์ฌ๊ฒฐ์ ์ ์ํ ์ผ๋๋ค ํต์ ํจํด์ ๋ฐฐ์๋๋ค.
๋ฐฐ์ธ ๋ด์ฉ:
broadcast()๋ก ๊ณ์ฐ๋ ๊ฐ์ ๋ชจ๋ ๋ ์ธ์ ๊ณต์- ๋ธ๋ก ๋ ๋ฒจ ํต๊ณ์ ์งํฉ์ ์์ฌ๊ฒฐ์ ๊ตฌํ
- ๋ธ๋ก๋์บ์คํธ์ ์กฐ๊ฑด๋ถ ๋ก์ง ๊ฒฐํฉ
- ๊ณ ๊ธ ๋ธ๋ก๋์บ์คํธ-์ ํ ์กฐ์ ํจํด
ํต์ฌ ํจํด:
var shared_value = 0.0
if lane == 0:
shared_value = compute_block_statistic()
shared_value = broadcast(shared_value)
result = use_shared_value(shared_value, local_data)
ํต์ฌ ๊ฐ๋
ํต์ ํจํด
์ํ ํต์ ์ ๊ธฐ๋ณธ ํจ๋ฌ๋ค์์ ์ดํดํฉ๋๋ค:
- ์ด์ ํต์ : ๋ ์ธ ๊ฐ ์ธ์ ๋ฐ์ดํฐ ๊ตํ
- ์งํฉ ์กฐ์ : ํ๋์ ๋ ์ธ์์ ๋ชจ๋ ๋ ์ธ์ผ๋ก ์ ๋ณด ๊ณต์
- ์คํ ์ค ์ฐ์ฐ: ๊ณ ์ ๋ ํจํด์ผ๋ก ์ด์ ๋ฐ์ดํฐ ์ ๊ทผ
- ๊ฒฝ๊ณ ์ฒ๋ฆฌ: ์ํ ๊ฐ์ฅ์๋ฆฌ์์์ ํต์ ๊ด๋ฆฌ
ํ๋์จ์ด ์ต์ ํ
์ํ ํต์ ์ด GPU ํ๋์จ์ด์ ๋งคํ๋๋ ๋ฐฉ์์ ์ดํดํฉ๋๋ค:
- ๋ ์ง์คํฐ ํ์ผ ํต์ : ์ค๋ ๋ ๊ฐ ๋ ์ง์คํฐ ์ง์ ์ ๊ทผ
- SIMT ์คํ: ๋ชจ๋ ๋ ์ธ์ด ํต์ ์ ๋์์ ์คํํฉ๋๋ค
- ์ ๋ก ์ง์ฐ ์๊ฐ: ์คํ ์ ๋ ๋ด์์ ํต์ ์ด ์๋ฃ๋ฉ๋๋ค
- ์๋ ๋๊ธฐํ: ๋ช ์์ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ์ง ์์ต๋๋ค
์๊ณ ๋ฆฌ์ฆ ๋ณํ
๊ธฐ์กด ๋ณ๋ ฌ ํจํด์ ์ํ ํต์ ์ผ๋ก ๋ณํํฉ๋๋ค:
- ๋ฐฐ์ด ์ด์ ์ ๊ทผ โ
shuffle_down() - ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์กฐ์ โ
broadcast() - ๋ณต์กํ ๊ฒฝ๊ณ ๋ก์ง โ ํ๋์จ์ด ์๋ ์ฒ๋ฆฌ
- ๋ค๋จ๊ณ ๋๊ธฐํ โ ๋จ์ผ ํต์ ์ฐ์ฐ
์์ํ๊ธฐ
์ด์ ๊ธฐ๋ฐ ์ ํ ์ฐ์ฐ์ผ๋ก ๊ธฐ์ด๋ฅผ ๋ค์ง ๋ค์, ๊ณ ๊ธ ์กฐ์ ์ ์ํ ์งํฉ ๋ธ๋ก๋์บ์คํธ ํจํด์ผ๋ก ๋์๊ฐ๋๋ค.
๐ก ์ฑ๊ณต ํ: ์ํ ํต์ ์ ๊ฐ์ ์ํ ๋ด ์ค๋ ๋ ๊ฐ์ ํ๋์จ์ด ๊ฐ์ ๋ฉ์์ง ํจ์ฑ์ผ๋ก ์๊ฐํ์ธ์. ์ด ๋ฉํ ๋ชจ๋ธ์ด GPU์ SIMT ์ํคํ ์ฒ๋ฅผ ํ์ฉํ๋ ํจ์จ์ ์ธ ํต์ ํจํด์ผ๋ก ์๋ดํ ๊ฒ์ ๋๋ค.
ํ์ต ๋ชฉํ: Puzzle 25๋ฅผ ๋ง์น๋ฉด, ์ํ ํต์ ์ด ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํจํด์ ๋์ฒดํ ์ ์๋ ์ํฉ์ ์ธ์ํ์ฌ ๋ ๊ฐ๋จํ๊ณ ๋น ๋ฅธ ์ด์ ๊ธฐ๋ฐ ์๊ณ ๋ฆฌ์ฆ๊ณผ ์กฐ์ ์๊ณ ๋ฆฌ์ฆ์ ์์ฑํ ์ ์๊ฒ ๋ฉ๋๋ค.
์์ํ๊ธฐ: warp.shuffle_down() ์์ ์ด์ ํต์ ์ ๋ฐฐ์ด ๋ค์, warp.broadcast() ์์ ์งํฉ ์กฐ์ ํจํด์ผ๋ก ๋์๊ฐ์ธ์.