LayoutTensor ์์๋ณด๊ธฐ
ํผ์ฆ ํ์ด๋ฅผ ์ ์ ๋ฉ์ถ๊ณ , GPU ํ๋ก๊ทธ๋๋ฐ์ ๋ ์ฆ๊ฒ๊ฒ ๋ง๋ค์ด์ค ๊ฐ๋ ฅํ ์ถ์ํ๋ฅผ ๋ฏธ๋ฆฌ ์ดํด๋ด ์๋ค: ๐ฅ โฆ ๋ฐ๋ก LayoutTensor ์ ๋๋ค.
๐ก LayoutTensor๊ฐ ์ด๋ค ์ผ์ ํ ์ ์๋์ง ๋ง๋ณด๊ธฐ๋ก ์ดํด๋ด ๋๋ค. ์ง๊ธ ๋ชจ๋ ๊ฑธ ์ดํดํ ํ์๋ ์์ด์ - ํผ์ฆ์ ์งํํ๋ฉด์ ๊ฐ ๊ธฐ๋ฅ์ ์์ธํ ์์๋ณผ ๊ฒ๋๋ค.
๋ฌธ์ : ์ ์ ๋ณต์กํด์ง๋ ์ฝ๋
์ง๊ธ๊น์ง ๊ฒช์ ์ด๋ ค์์ ์ดํด๋ด ์๋ค:
# Puzzle 1: ๋จ์ ์ธ๋ฑ์ฑ
output[i] = a[i] + 10.0
# Puzzle 2: ์ฌ๋ฌ ๋ฐฐ์ด ๊ด๋ฆฌ
output[i] = a[i] + b[i]
# Puzzle 3: ๊ฒฝ๊ณ ๊ฒ์ฌ
if i < size:
output[i] = a[i] + 10.0
์ฐจ์์ด ๋์ด๋๋ฉด ์ฝ๋๋ ๋ ๋ณต์กํด์ง๋๋ค:
# ์ ํต์ ์ธ 2D ์ธ๋ฑ์ฑ (ํ ์ฐ์ 2D ํ๋ ฌ)
idx = row * WIDTH + col
if row < height and col < width:
output[idx] = a[idx] + 10.0
ํด๊ฒฐ์ฑ : LayoutTensor ๋ฏธ๋ฆฌ๋ณด๊ธฐ
LayoutTensor๋ ์ด๋ฐ ๋ฌธ์ ๋ค์ ๊น๋ํ๊ฒ ํด๊ฒฐํด์ค๋๋ค. ์์ผ๋ก ๋ฐฐ์ธ ๋ด์ฉ์ ์ด์ง ์ฟ๋ณด๋ฉด:
- ์์ฐ์ค๋ฌ์ด ์ธ๋ฑ์ฑ: ์๋ ์คํ์
๊ณ์ฐ ๋์
tensor[i, j]์ฌ์ฉ - ์ ์ฐํ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์: ํ ์ฐ์ , ์ด ์ฐ์ , ํ์ผ ๊ตฌ์ฑ ์ง์
- ์ฑ๋ฅ ์ต์ ํ: GPU์ ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด
์์ผ๋ก ๋ฐฐ์ธ ๋ด์ฉ ๋ง๋ณด๊ธฐ
LayoutTensor๊ฐ ํ ์ ์๋ ์ผ์ ๋ช ๊ฐ์ง ์์๋ก ์ดํด๋ด ์๋ค. ์ง๊ธ ๋ชจ๋ ์ธ๋ถ ์ฌํญ์ ์ดํดํ ํ์๋ ์์ต๋๋ค - ์์ผ๋ก ๋์ฌ ํผ์ฆ์์ ๊ฐ ๊ธฐ๋ฅ์ ๊ผผ๊ผผํ ๋ค๋ฃฐ ๊ฑฐ์์.
๊ธฐ๋ณธ ์ฌ์ฉ ์์
from layout import Layout, LayoutTensor
# ๋ ์ด์์ ์ ์
comptime HEIGHT = 2
comptime WIDTH = 3
comptime layout = Layout.row_major(HEIGHT, WIDTH)
# ํ
์ ์์ฑ
tensor = LayoutTensor[dtype, layout](buffer.unsafe_ptr())
# ์์ฐ์ค๋ฝ๊ฒ ์์ ์ ๊ทผ
tensor[0, 0] = 1.0 # ์ฒซ ๋ฒ์งธ ์์
tensor[1, 2] = 2.0 # ๋ง์ง๋ง ์์
Layout๊ณผ LayoutTensor์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด Mojo ๋งค๋ด์ผ์ ๊ฐ์ด๋๋ฅผ ์ฐธ๊ณ ํ์ธ์:
๊ฐ๋จํ ์์
LayoutTensor์ ๊ธฐ๋ณธ์ ๋ณด์ฌ์ฃผ๋ ๊ฐ๋จํ ์์ ๋ก ๋ชจ๋ ๊ฒ์ ์ ๋ฆฌํด๋ด ์๋ค:
from gpu.host import DeviceContext
from layout import Layout, LayoutTensor
comptime HEIGHT = 2
comptime WIDTH = 3
comptime dtype = DType.float32
comptime layout = Layout.row_major(HEIGHT, WIDTH)
fn kernel[
dtype: DType, layout: Layout
](tensor: LayoutTensor[dtype, layout, MutAnyOrigin]):
print("Before:")
print(tensor)
tensor[0, 0] += 1
print("After:")
print(tensor)
def main() raises:
ctx = DeviceContext()
a = ctx.enqueue_create_buffer[dtype](HEIGHT * WIDTH)
a.enqueue_fill(0)
tensor = LayoutTensor[dtype, layout, MutAnyOrigin](a)
# Note: since `tensor` is a device tensor we can't print it without the kernel wrapper
ctx.enqueue_function[kernel[dtype, layout], kernel[dtype, layout]](
tensor, grid_dim=1, block_dim=1
)
ctx.synchronize()
๋ค์ ๋ช ๋ น์ด๋ก ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด:
pixi run layout_tensor_intro
pixi run -e amd layout_tensor_intro
pixi run -e apple layout_tensor_intro
uv run poe layout_tensor_intro
Before:
0.0 0.0 0.0
0.0 0.0 0.0
After:
1.0 0.0 0.0
0.0 0.0 0.0
๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ์ดํด๋ด ์๋ค:
- ํ ์ฐ์ ๋ ์ด์์์ผ๋ก
2 x 3ํ ์๋ฅผ ์์ฑํฉ๋๋ค - ์ฒ์์๋ ๋ชจ๋ ์์๊ฐ 0์ ๋๋ค
- ์์ฐ์ค๋ฌ์ด ์ธ๋ฑ์ฑ์ผ๋ก ํ๋์ ์์๋ฅผ ์์ ํฉ๋๋ค
- ๋ณ๊ฒฝ ์ฌํญ์ด ์ถ๋ ฅ์ ๋ฐ์๋ฉ๋๋ค
์ด ๊ฐ๋จํ ์์ ๋ LayoutTensor์ ํต์ฌ ์ฅ์ ์ ๋ณด์ฌ์ค๋๋ค:
- ํ ์ ์์ฑ๊ณผ ์ ๊ทผ์ ์ํ ๊น๋ํ ๋ฌธ๋ฒ
- ์๋ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ ์ฒ๋ฆฌ
- ์์ฐ์ค๋ฌ์ด ๋ค์ฐจ์ ์ธ๋ฑ์ฑ
์ด ์์ ๋ ๊ฐ๋จํ์ง๋ง, ๊ฐ์ ํจํด์ด ์์ผ๋ก ๋์ฌ ํผ์ฆ์ ๋ณต์กํ GPU ์ฐ์ฐ์๋ ๊ทธ๋๋ก ์ ์ฉ๋ฉ๋๋ค. ์ด๋ฐ ๊ธฐ๋ณธ ๊ฐ๋ ์ด ๋ค์์ผ๋ก ์ด๋ป๊ฒ ํ์ฅ๋๋์ง ๋ณด๊ฒ ๋ ๊ฑฐ์์:
- ๋ฉํฐ ์ค๋ ๋ GPU ์ฐ์ฐ
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
- ๋ณต์กํ ํ์ผ๋ง ์ ๋ต
- ํ๋์จ์ด ๊ฐ์ ์ฐ์ฐ
LayoutTensor์ ํจ๊ป GPU ํ๋ก๊ทธ๋๋ฐ ์ฌ์ ์ ์์ํ ์ค๋น๊ฐ ๋๋์? ํผ์ฆ๋ก ๋ค์ด๊ฐ๋ด ์๋ค!
๐ก ํ: ์งํํ๋ฉด์ ์ด ์์ ๋ฅผ ๊ธฐ์ตํด๋์ธ์ - ์ด ๊ธฐ๋ณธ ๊ฐ๋ ์ ๋ฐํ์ผ๋ก ์ ์ ๋ ์ ๊ตํ GPU ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๊ฐ ๊ฒ๋๋ค.