๊ฐ์
1D LayoutTensor a์ ๊ฐ ์์น์ 10์ ๋ํด 1D LayoutTensor output์ ์ ์ฅํ๋ ์ปค๋์ ๊ตฌํํด ๋ณด์ธ์.
์ฐธ๊ณ : ๋ธ๋ก๋น ์ค๋ ๋ ์๊ฐ a์ ํฌ๊ธฐ๋ณด๋ค ์์ต๋๋ค.
ํต์ฌ ๊ฐ๋
์ด ํผ์ฆ์์ ๋ฐฐ์ธ ๋ด์ฉ:
- address_space๋ฅผ ํ์ฉํ LayoutTensor์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฅ
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋์ ์ค๋ ๋ ๋๊ธฐํ
- LayoutTensor๋ก ๋ธ๋ก ๋ก์ปฌ ๋ฐ์ดํฐ ๊ด๋ฆฌํ๊ธฐ
ํต์ฌ์ LayoutTensor๊ฐ ๋ธ๋ก ๋ก์ปฌ ์ ์ฅ์์ ์ฑ๋ฅ์ ๊ทธ๋๋ก ์ ์งํ๋ฉด์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ผ๋ง๋ ๊ฐ์ํํ๋์ง ์ดํดํ๋ ๊ฒ์ ๋๋ค.
๊ตฌ์ฑ
- ๋ฐฐ์ด ํฌ๊ธฐ:
SIZE = 8์์ - ๋ธ๋ก๋น ์ค๋ ๋ ์:
TPB = 4 - ๋ธ๋ก ์: 2
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ: ๋ธ๋ก๋น
TPB๊ฐ ์์
์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฉ์๊ณผ์ ์ฃผ์ ์ฐจ์ด์
-
๋ฉ๋ชจ๋ฆฌ ํ ๋น: stack_allocation ๋์ address_space๋ฅผ ์ฌ์ฉํ LayoutTensor ์ฌ์ฉ
# ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฉ์ shared = stack_allocation[TPB, Scalar[dtype]]() # LayoutTensor ๋ฐฉ์ shared = LayoutTensor[dtype, Layout.row_major(TPB), MutAnyOrigin, address_space = AddressSpace.SHARED].stack_allocation() -
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ: ๋์ผํ ๋ฌธ๋ฒ
# ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฉ์ shared[local_i] = a[global_i] # LayoutTensor ๋ฐฉ์ shared[local_i] = a[global_i] -
์์ ๊ธฐ๋ฅ:
- ํ์ ์์ ์ฑ
- ๋ ์ด์์ ๊ด๋ฆฌ
- ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ ์ฒ๋ฆฌ
์ฐธ๊ณ : LayoutTensor๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ ์ฒ๋ฆฌํ์ง๋ง, ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ์
barrier()๋ฅผ ํตํ ์ค๋ ๋ ๋๊ธฐํ๋ ์ฌ์ ํ ์ง์ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
ํ์ต ์ฐธ๊ณ : ์ด ํผ์ฆ์์๋ ๊ฐ ์ค๋ ๋๊ฐ ์์ ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์น์๋ง ์ ๊ทผํ๋ฏ๋ก barrier()๊ฐ ์๋ฐํ ํ์ํ์ง ์์ต๋๋ค. ํ์ง๋ง ๋ ๋ณต์กํ ์ํฉ์์ ํ์ํ ์ฌ๋ฐ๋ฅธ ๋๊ธฐํ ํจํด์ ์ตํ๊ธฐ ์ํด ํฌํจ๋์ด ์์ต๋๋ค.
์์ฑํ ์ฝ๋
comptime TPB = 4
comptime SIZE = 8
comptime BLOCKS_PER_GRID = (2, 1)
comptime THREADS_PER_BLOCK = (TPB, 1)
comptime dtype = DType.float32
comptime layout = Layout.row_major(SIZE)
fn add_10_shared_layout_tensor[
layout: Layout
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: UInt,
):
# Allocate shared memory using LayoutTensor with explicit address_space
shared = LayoutTensor[
dtype,
Layout.row_major(TPB),
MutAnyOrigin,
address_space = AddressSpace.SHARED,
].stack_allocation()
global_i = block_dim.x * block_idx.x + thread_idx.x
local_i = thread_idx.x
if global_i < size:
shared[local_i] = a[global_i]
barrier()
# FILL ME IN (roughly 2 lines)
์ ์ฒด ์ฝ๋ ๋ณด๊ธฐ: problems/p08/p08_layout_tensor.mojo
ํ
- address_space ํ๋ผ๋ฏธํฐ๋ก LayoutTensor ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์ฑ
- ์์ฐ์ค๋ฌ์ด ์ธ๋ฑ์ฑ์ผ๋ก ๋ฐ์ดํฐ ๋ก๋:
shared[local_i] = a[global_i] barrier()๋ก ๋๊ธฐํ (ํ์ต์ฉ - ์ฌ๊ธฐ์๋ ์๋ฐํ ํ์ํ์ง ์์)- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ธ๋ฑ์ค๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ๋ฒ์๋ฅผ ๋ฒ์ด๋ ์ ๊ทผ์ ๋ฐฉ์งํ๋ ๊ฐ๋
์ฝ๋ ์คํ
์๋ฃจ์ ์ ํ ์คํธํ๋ ค๋ฉด ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์:
pixi run p08_layout_tensor
pixi run -e amd p08_layout_tensor
pixi run -e apple p08_layout_tensor
uv run poe p08_layout_tensor
ํผ์ฆ์ ์์ง ํ์ง ์์๋ค๋ฉด ์ถ๋ ฅ์ด ๋ค์๊ณผ ๊ฐ์ด ๋ํ๋ฉ๋๋ค:
out: HostBuffer([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
expected: HostBuffer([11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0])
์๋ฃจ์
fn add_10_shared_layout_tensor[
layout: Layout
](
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: UInt,
):
# Allocate shared memory using tensor builder
shared = LayoutTensor[
dtype,
Layout.row_major(TPB),
MutAnyOrigin,
address_space = AddressSpace.SHARED,
].stack_allocation()
global_i = block_dim.x * block_idx.x + thread_idx.x
local_i = thread_idx.x
if global_i < size:
shared[local_i] = a[global_i]
# Note: barrier is not strictly needed here since each thread only accesses
# its own shared memory location. However, it's included to teach proper
# shared memory synchronization patterns for more complex scenarios where
# threads need to coordinate access to shared data.
barrier()
if global_i < size:
output[global_i] = shared[local_i] + 10
LayoutTensor๊ฐ ์ฑ๋ฅ์ ์ ์งํ๋ฉด์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ผ๋ง๋ ๊ฐ์ํํ๋์ง ๋ณด์ฌ์ฃผ๋ ์๋ฃจ์ ์ ๋๋ค:
-
LayoutTensor๋ฅผ ์ฌ์ฉํ ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ
-
์ ์ญ ํ ์:
a์output(๋๋ฆผ, ๋ชจ๋ ๋ธ๋ก์์ ๋ณด์) -
๊ณต์ ํ ์:
shared(๋น ๋ฆ, ์ค๋ ๋ ๋ธ๋ก ๋ก์ปฌ) -
๋ธ๋ก๋น 4๊ฐ ์ค๋ ๋๋ก 8๊ฐ ์์๋ฅผ ์ฒ๋ฆฌํ๋ ์์:
์ ์ญ ํ ์ a: [1 1 1 1 | 1 1 1 1] # ์ ๋ ฅ: ๋ชจ๋ 1 Block (0): Block (1): shared[0..3] shared[0..3] [1 1 1 1] [1 1 1 1]
-
-
์ค๋ ๋ ์กฐ์จ
-
๋ก๋ ๋จ๊ณ (์์ฐ์ค๋ฌ์ด ์ธ๋ฑ์ฑ ์ฌ์ฉ):
Thread 0: shared[0] = a[0]=1 Thread 2: shared[2] = a[2]=1 Thread 1: shared[1] = a[1]=1 Thread 3: shared[3] = a[3]=1 barrier() โ โ โ โ # ๋ชจ๋ ๋ก๋ ์๋ฃ ๋๊ธฐ -
์ฒ๋ฆฌ ๋จ๊ณ: ๊ฐ ์ค๋ ๋๊ฐ ์์ ์ ๊ณต์ ํ ์ ๊ฐ์ 10์ ๋ํจ
-
๊ฒฐ๊ณผ:
output[global_i] = shared[local_i] + 10 = 11
์ฐธ๊ณ : ์ด ๊ฒฝ์ฐ์๋ ๊ฐ ์ค๋ ๋๊ฐ ์์ ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์น(
shared[local_i])์๋ง ์ฐ๊ณ ์ฝ์ผ๋ฏ๋กbarrier()๊ฐ ์๋ฐํ ํ์ํ์ง ์์ต๋๋ค. ํ์ง๋ง ์ค๋ ๋๋ค์ด ์๋ก์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ์ํฉ์์ ํ์์ ์ธ ๋๊ธฐํ ํจํด์ ์ตํ๊ธฐ ์ํด ํฌํจ๋์ด ์์ต๋๋ค. -
-
LayoutTensor์ ์ฅ์
-
๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น:
# address_space๋ฅผ ์ฌ์ฉํ ๊น๋ํ LayoutTensor API shared = LayoutTensor[dtype, Layout.row_major(TPB), MutAnyOrigin, address_space = AddressSpace.SHARED].stack_allocation() -
์ ์ญ๊ณผ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ ์์ฐ์ค๋ฌ์ด ์ธ๋ฑ์ฑ:
Block 0 ์ถ๋ ฅ: [11 11 11 11] Block 1 ์ถ๋ ฅ: [11 11 11 11] -
๋ด์ฅ๋ ๋ ์ด์์ ๊ด๋ฆฌ์ ํ์ ์์ ์ฑ
-
-
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด
- ๋ก๋: ์ ์ญ ํ ์ โ ๊ณต์ ํ ์ (์ต์ ํ๋จ)
- ๋๊ธฐํ: ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฒ์ ๊ณผ ๋์ผํ
barrier()ํ์ - ์ฒ๋ฆฌ: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ 10 ๋ํ๊ธฐ
- ์ ์ฅ: ๊ฒฐ๊ณผ(11)๋ฅผ ์ ์ญ ํ ์์ ์ฐ๊ธฐ
์ด ํจํด์ LayoutTensor๊ฐ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ ์ด์ ์ ์ ์งํ๋ฉด์ ๋ ํธ๋ฆฌํ API์ ๋ด์ฅ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.