์ ์ญ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๊ธฐ๋ณธ ๋ฒ์
๊ฐ์
์ ๋ฐฉ ํ๋ ฌ \(A\)์ \(B\)๋ฅผ ๊ณฑํ์ฌ ๊ฒฐ๊ณผ๋ฅผ \(\text{output}\)์ ์ ์ฅํ๋ ์ปค๋์ ๊ตฌํํ์ธ์. ๊ฐ ์ค๋ ๋๊ฐ ์ถ๋ ฅ ํ๋ ฌ์ ์์ ํ๋๋ฅผ ๊ณ์ฐํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ์ ๋๋ค.
ํต์ฌ ๊ฐ๋
์ด ํผ์ฆ์์ ๋ค๋ฃจ๋ ๋ด์ฉ:
- ํ๋ ฌ ์ฐ์ฐ์ ์ํ 2D ์ค๋ ๋ ๊ตฌ์ฑ
- ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด
- ํ ์ฐ์ (row-major) ๋ ์ด์์์์์ ํ๋ ฌ ์ธ๋ฑ์ฑ
- ์ค๋ ๋์ ์ถ๋ ฅ ์์ ๊ฐ ๋งคํ
ํต์ฌ์ 2D ์ค๋ ๋ ์ธ๋ฑ์ค๋ฅผ ํ๋ ฌ ์์์ ๋งคํํ๊ณ , ๋ด์ ์ ๋ณ๋ ฌ๋ก ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๊ฒ์ ๋๋ค.
๊ตฌ์ฑ
- ํ๋ ฌ ํฌ๊ธฐ: \(\text{SIZE} \times \text{SIZE} = 2 \times 2\)
- ๋ธ๋ก๋น ์ค๋ ๋ ์: \(\text{TPB} \times \text{TPB} = 3 \times 3\)
- ๊ทธ๋ฆฌ๋ ์ฐจ์: \(1 \times 1\)
๋ ์ด์์ ๊ตฌ์ฑ:
- ์
๋ ฅ A:
Layout.row_major(SIZE, SIZE) - ์
๋ ฅ B:
Layout.row_major(SIZE, SIZE) - ์ถ๋ ฅ:
Layout.row_major(SIZE, SIZE)
์์ฑํ ์ฝ๋
from gpu import thread_idx, block_idx, block_dim, barrier
from gpu.memory import AddressSpace
from layout import Layout, LayoutTensor
comptime TPB = 3
comptime SIZE = 2
comptime BLOCKS_PER_GRID = (1, 1)
comptime THREADS_PER_BLOCK = (TPB, TPB)
comptime dtype = DType.float32
comptime layout = Layout.row_major(SIZE, SIZE)
fn naive_matmul[
layout: Layout, size: UInt
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
b: LayoutTensor[dtype, layout, ImmutAnyOrigin],
):
row = block_dim.y * block_idx.y + thread_idx.y
col = block_dim.x * block_idx.x + thread_idx.x
# FILL ME IN (roughly 6 lines)
์ ์ฒด ํ์ผ ๋ณด๊ธฐ: problems/p16/p16.mojo
ํ
- ์ค๋ ๋ ์ธ๋ฑ์ค๋ก
row์col๊ณ์ฐ - ์ธ๋ฑ์ค๊ฐ
size๋ฒ์ ์์ ์๋์ง ํ์ธ - ๋ก์ปฌ ๋ณ์์ ๊ณฑ์ ํฉ ๋์
- ์ต์ข ํฉ์ ์ฌ๋ฐ๋ฅธ ์ถ๋ ฅ ์์น์ ๊ธฐ๋ก
์ฝ๋ ์คํ
์๋ฃจ์ ์ ํ ์คํธํ๋ ค๋ฉด ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์:
pixi run p16 --naive
pixi run -e amd p16 --naive
pixi run -e apple p16 --naive
uv run poe p16 --naive
ํผ์ฆ์ ์์ง ํ์ง ์์๋ค๋ฉด ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
out: HostBuffer([0.0, 0.0, 0.0, 0.0])
expected: HostBuffer([4.0, 6.0, 12.0, 22.0])
์๋ฃจ์
fn naive_matmul[
layout: Layout, size: UInt
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
b: LayoutTensor[dtype, layout, ImmutAnyOrigin],
):
row = block_dim.y * block_idx.y + thread_idx.y
col = block_dim.x * block_idx.x + thread_idx.x
if row < size and col < size:
var acc: output.element_type = 0
@parameter
for k in range(size):
acc += a[row, k] * b[k, col]
output[row, col] = acc
LayoutTensor๋ฅผ ํ์ฉํ ๊ธฐ๋ณธ ํ๋ ฌ ๊ณฑ์ ์ ๋ค์๊ณผ ๊ฐ์ ์ ๊ทผ ๋ฐฉ์์ ๋ฐ๋ฆ ๋๋ค:
ํ๋ ฌ ๋ ์ด์์ (2ร2 ์์)
Matrix A: Matrix B: Output C:
[a[0,0] a[0,1]] [b[0,0] b[0,1]] [c[0,0] c[0,1]]
[a[1,0] a[1,1]] [b[1,0] b[1,1]] [c[1,0] c[1,1]]
๊ตฌํ ์์ธ
-
์ค๋ ๋ ๋งคํ:
row = block_dim.y * block_idx.y + thread_idx.y col = block_dim.x * block_idx.x + thread_idx.x -
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด:
- ์ง์ 2D ์ธ๋ฑ์ฑ:
a[row, k] - ์ ์น ์ ๊ทผ:
b[k, col] - ์ถ๋ ฅ ๊ธฐ๋ก:
output[row, col]
- ์ง์ 2D ์ธ๋ฑ์ฑ:
-
์ฐ์ฐ ํ๋ฆ:
# var๋ก ๊ฐ๋ณ ๋์ ๋ณ์๋ฅผ ์ ์ธํ๊ณ ํ ์์ ์์ ํ์ ์ ์ฌ์ฉ var acc: output.element_type = 0 # @parameter๋ก ์ปดํ์ผ ํ์ ๋ฃจํ ์ ๊ฐ @parameter for k in range(size): acc += a[row, k] * b[k, col]
์ฃผ์ ์ธ์ด ๊ธฐ๋ฅ
-
๋ณ์ ์ ์ธ:
var acc: output.element_type = 0์์var๋ก ๊ฐ๋ณ ๋ณ์๋ฅผ ์ ์ธํ๊ณ ,output.element_type์ผ๋ก ์ถ๋ ฅ ํ ์์ ๋์ผํ ํ์ ์ ์ง์ ํฉ๋๋ค- ๋์ ์ฐ์ฐ ์ ์ 0์ผ๋ก ์ด๊ธฐํ
-
๋ฃจํ ์ต์ ํ:
@parameter๋ฐ์ฝ๋ ์ดํฐ๋ก ์ปดํ์ผ ํ์์ ๋ฃจํ ์ ๊ฐ- ํฌ๊ธฐ๊ฐ ์๊ณ ๋ฏธ๋ฆฌ ์๋ ค์ง ํ๋ ฌ์์ ์ฑ๋ฅ ํฅ์
- ๋ ๋์ ๋ช ๋ น์ด ์ค์ผ์ค๋ง ๊ฐ๋ฅ
์ฑ๋ฅ ํน์ฑ
-
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ:
- ๊ฐ ์ค๋ ๋๊ฐ
2 x SIZEํ ์ ์ญ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฝ์ - ์ค๋ ๋๋น ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ 1ํ
- ์ค๋ ๋ ๊ฐ ๋ฐ์ดํฐ ์ฌ์ฌ์ฉ ์์
- ๊ฐ ์ค๋ ๋๊ฐ
-
์ฐ์ฐ ํจ์จ:
- ๋จ์ํ ๊ตฌํ์ด์ง๋ง ์ฑ๋ฅ์ ์ต์ ์ด ์๋
- ์ ์ญ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ค๋ณต์ผ๋ก ๋ง์ด ์ฝ์
- ๋น ๋ฅธ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ฉํ์ง ์์
-
ํ๊ณ:
- ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ์ ๋ง์ด ์๋ชจ
- ๋ฎ์ ๋ฐ์ดํฐ ์ง์ญ์ฑ
- ํฐ ํ๋ ฌ๋ก ๊ฐ์๋ก ํ์ฅ์ฑ ๋ถ์กฑ
์ด ๊ธฐ๋ณธ ๊ตฌํ์ GPU ํ๋ ฌ ๊ณฑ์ ์ ์ดํดํ๊ธฐ ์ํ ๊ธฐ์ค์ ์ผ๋ก, ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ์ต์ ํํด์ผ ํ๋ ์ด์ ๋ฅผ ๋ณด์ฌ์ค๋๋ค.