๋ค๋จ๊ณ ํ์ดํ๋ผ์ธ ์กฐ์
๊ฐ์
์กฐ์จ๋ 3๋จ๊ณ ํ์ดํ๋ผ์ธ์ ํตํด ์ด๋ฏธ์ง๋ฅผ ์ฒ๋ฆฌํ๋ ์ปค๋์ ๊ตฌํํฉ๋๋ค. ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ํนํ๋ ์ฒ๋ฆฌ ๋จ๊ณ๋ฅผ ๋ด๋นํ๊ณ , ๋ช ์์ ๋ฐฐ๋ฆฌ์ด๋ก ๋๊ธฐํ๋ฉ๋๋ค.
์ฐธ๊ณ : ์ค๋ ๋ ์ญํ ์ด ํนํ๋์ด ์์ต๋๋ค: Stage 1 (์ค๋ ๋ 0-127)์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ณ ์ ์ฒ๋ฆฌํ๋ฉฐ, Stage 2 (์ค๋ ๋ 128-255)๋ ๋ธ๋ฌ ์ฐ์ฐ์ ์ ์ฉํ๊ณ , Stage 3 (์ ์ฒด ์ค๋ ๋)์ ์ต์ข ์ค๋ฌด๋ฉ์ ์ํํฉ๋๋ค.
์๊ณ ๋ฆฌ์ฆ ์ํคํ ์ฒ: ์ด ํผ์ฆ์ ํ๋์ GPU ๋ธ๋ก ์์์ ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์์ ํ ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๋ ์์ฐ์-์๋น์ ํ์ดํ๋ผ์ธ์ ๊ตฌํํฉ๋๋ค. ๋ชจ๋ ์ค๋ ๋๊ฐ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ์ ๋ํด ๋์ผํ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๋ ์ ํต์ ์ธ GPU ํ๋ก๊ทธ๋๋ฐ๊ณผ ๋ฌ๋ฆฌ, ์ด ์ ๊ทผ ๋ฐฉ์์ ์ค๋ ๋๋ฅผ ๊ธฐ๋ฅ๋ณ๋ก ํนํํ์ฌ ๋ถํ ํฉ๋๋ค.
ํ์ดํ๋ผ์ธ ๊ฐ๋ : ์๊ณ ๋ฆฌ์ฆ์ ์ธ ๊ฐ์ ๊ตฌ๋ถ๋ ๋จ๊ณ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ฉฐ, ๊ฐ ๋จ๊ณ์๋ ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๋ ํนํ๋ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์์ต๋๋ค. ๊ฐ ๋จ๊ณ๋ ๋ค์ ๋จ๊ณ๊ฐ ์๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ์ฌ, ๋ฐฐ๋ฆฌ์ด๋ก ์ ์คํ๊ฒ ๋๊ธฐํํด์ผ ํ๋ ๋ช ์์ ์์ฐ์-์๋น์ ๊ด๊ณ๋ฅผ ๋ง๋ญ๋๋ค.
๋ฐ์ดํฐ ์์กด์ฑ๊ณผ ๋๊ธฐํ: ๊ฐ ๋จ๊ณ๋ ๋ค์ ๋จ๊ณ๊ฐ ์๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค:
- Stage 1 โ Stage 2: ์ฒซ ๋ฒ์งธ ๋จ๊ณ๊ฐ ๋ธ๋ฌ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ ์ฒ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์์ฑ
- Stage 2 โ Stage 3: ๋ ๋ฒ์งธ ๋จ๊ณ๊ฐ ์ต์ข ์ค๋ฌด๋ฉ์ ์ํ ๋ธ๋ฌ ๊ฒฐ๊ณผ๋ฅผ ์์ฑ
- ๋ฐฐ๋ฆฌ์ด๊ฐ ๊ฒฝ์ ์ํ๋ฅผ ๋ฐฉ์ง: ์์กดํ๋ ๋จ๊ณ๊ฐ ์์๋๊ธฐ ์ ์ ํด๋น ๋จ๊ณ๊ฐ ์์ ํ ์๋ฃ๋๋๋ก ๋ณด์ฅ
๊ตฌ์ฒด์ ์ผ๋ก, ๋ค๋จ๊ณ ํ์ดํ๋ผ์ธ์ ์ธ ๊ฐ์ง ์ํ ์ฐ์ฐ์ผ๋ก ๊ตฌ์ฑ๋ ์กฐ์จ๋ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํฉ๋๋ค:
Stage 1 - ์ ์ฒ๋ฆฌ ๊ฐํ:
\[P[i] = I[i] \times 1.1\]
์ฌ๊ธฐ์ \(P[i]\)๋ ์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ์ด๊ณ \(I[i]\)๋ ์ ๋ ฅ ๋ฐ์ดํฐ์ ๋๋ค.
Stage 2 - ์ํ ๋ธ๋ฌ ํํฐ:
\[B[i] = \frac{1}{N_i} \sum_{k=-2}^{2} P[i+k] \quad \text{where} i+k \in [0, 255]\]
์ฌ๊ธฐ์ \(B[i]\)๋ ๋ธ๋ฌ ๊ฒฐ๊ณผ์ด๊ณ , \(N_i\)๋ ํ์ผ ๊ฒฝ๊ณ ๋ด์ ์ ํจํ ์ด์ ์์ ๋๋ค.
Stage 3 - ์ฐ์์ ์ด์ ์ค๋ฌด๋ฉ:
\[F[i] = \begin{cases} (B[i] + B[i+1]) \times 0.6 & \text{if } i = 0 \\ ((B[i] + B[i-1]) \times 0.6 + B[i+1]) \times 0.6 & \text{if } 0 < i < 255 \\ (B[i] + B[i-1]) \times 0.6 & \text{if } i = 255 \end{cases}\]
์ฌ๊ธฐ์ \(F[i]\)๋ ์ฐ์์ ์ค๋ฌด๋ฉ์ด ์ ์ฉ๋ ์ต์ข ์ถ๋ ฅ์ ๋๋ค.
์ค๋ ๋ ํนํ:
- ์ค๋ ๋ 0-127: \(i \in \{0, 1, 2, \ldots, 255\}\)์ ๋ํด \(P[i]\) ๊ณ์ฐ (์ค๋ ๋๋น 2๊ฐ ์์)
- ์ค๋ ๋ 128-255: \(i \in \{0, 1, 2, \ldots, 255\}\)์ ๋ํด \(B[i]\) ๊ณ์ฐ (์ค๋ ๋๋น 2๊ฐ ์์)
- ์ ์ฒด 256๊ฐ ์ค๋ ๋: \(i \in \{0, 1, 2, \ldots, 255\}\)์ ๋ํด \(F[i]\) ๊ณ์ฐ (์ค๋ ๋๋น 1๊ฐ ์์)
๋๊ธฐํ ์ง์ :
\[\text{barrier}_1 \Rightarrow P[i] \text{ complete} \Rightarrow \text{barrier}_2 \Rightarrow B[i] \text{ complete} \Rightarrow \text{barrier}_3 \Rightarrow F[i] \text{ complete}\]
ํต์ฌ ๊ฐ๋
์ด ํผ์ฆ์์๋ ๋ค์์ ๋ฐฐ์๋๋ค:
- ํ๋์ GPU ๋ธ๋ก ์์์ ์ค๋ ๋ ์ญํ ํนํ ๊ตฌํ
- ์ฒ๋ฆฌ ๋จ๊ณ ๊ฐ ์์ฐ์-์๋น์ ๊ด๊ณ ์กฐ์จ
- ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์ ๋๊ธฐํ๋ฅผ ์ํ ๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ (๋์ผํ ์๊ณ ๋ฆฌ์ฆ ๋ด๋ถ๋ฟ ์๋๋ผ)
ํต์ฌ ํต์ฐฐ์ ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์์ ํ ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๋ฉด์ ์ ๋ต์ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น๋ฅผ ํตํด ์กฐ์จ๋๋ ๋ค๋จ๊ณ ํ์ดํ๋ผ์ธ์ ์ด๋ป๊ฒ ์ค๊ณํ๋์ง ์ดํดํ๋ ๊ฒ์ ๋๋ค.
์ ์ค์ํ๊ฐ: ๋๋ถ๋ถ์ GPU ํํ ๋ฆฌ์ผ์ ๋จ์ผ ์๊ณ ๋ฆฌ์ฆ ๋ด์์์ ๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ๋ฒ - ๋ฆฌ๋์ ์ด๋ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฐ์ฐ ์ค ์ค๋ ๋๋ฅผ ๋๊ธฐํํ๋ ๊ฒ - ์ ๊ฐ๋ฅด์นฉ๋๋ค. ํ์ง๋ง ์ค์ GPU ์๊ณ ๋ฆฌ์ฆ์์๋ ์ ์คํ๊ฒ ์กฐ์จํด์ผ ํ๋ ์ฌ๋ฌ ๊ฐ์ ๊ตฌ๋ถ๋ ์ฒ๋ฆฌ ๋จ๊ณ๋ฅผ ํฌํจํ๋ ์ํคํ ์ฒ์ ๋ณต์ก์ฑ์ด ํ์ํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ด ํผ์ฆ์ ๋จ์ผ์ฒด์ ์๊ณ ๋ฆฌ์ฆ์ ํนํ๋๊ณ ์กฐ์จ๋ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
์ด์ ํผ์ฆ๊ณผ ํ์ฌ์ ๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ ๋น๊ต:
- ์ด์ ํผ์ฆ (P8, P12, P15): ๋ชจ๋ ์ค๋ ๋๊ฐ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๊ณ , ๋ฐฐ๋ฆฌ์ด๋ ์๊ณ ๋ฆฌ์ฆ ๋จ๊ณ ๋ด์์ ๋๊ธฐํ
- ์ด ํผ์ฆ: ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํํ๊ณ , ๋ฐฐ๋ฆฌ์ด๋ ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์ ์กฐ์จ
์ค๋ ๋ ํนํ ์ํคํ ์ฒ: ์ค๋ ๋๊ฐ ๋ฐ์ดํฐ ์ธ๋ฑ์ค๋ง ๋ค๋ฅธ ๋ฐ์ดํฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ๋ฌ๋ฆฌ, ์ด ํผ์ฆ์ ํ์ดํ๋ผ์ธ์์์ ์ญํ ์ ๋ฐ๋ผ ์ค๋ ๋๊ฐ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅธ ์ฝ๋ ๊ฒฝ๋ก๋ฅผ ์คํํ๋ ์๊ณ ๋ฆฌ์ฆ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํฉ๋๋ค.
๊ตฌ์ฑ
์์คํ ๋งค๊ฐ๋ณ์:
- ์ด๋ฏธ์ง ํฌ๊ธฐ:
SIZE = 1024์์ (๊ฐ์ํ๋ฅผ ์ํด 1D) - ๋ธ๋ก๋น ์ค๋ ๋ ์:
TPB = 256์ค๋ ๋,(256, 1)๋ธ๋ก ์ฐจ์์ผ๋ก ๊ตฌ์ฑ - ๊ทธ๋ฆฌ๋ ๊ตฌ์ฑ: ์ ์ฒด ์ด๋ฏธ์ง๋ฅผ ํ์ผ ๋จ์๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํ
(4, 1)๋ธ๋ก (์ด 4๊ฐ ๋ธ๋ก) - ๋ฐ์ดํฐ ํ์
: ๋ชจ๋ ์ฐ์ฐ์
DType.float32
์ค๋ ๋ ํนํ ์ํคํ ์ฒ:
-
Stage 1 ์ค๋ ๋:
STAGE1_THREADS = 128(์ค๋ ๋ 0-127, ๋ธ๋ก์ ์ ๋ฐ๋ถ)- ์ญํ : ์ ์ญ ๋ฉ๋ชจ๋ฆฌ์์ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ณ ์ ์ฒ๋ฆฌ ์ ์ฉ
- ์์ ๋ถ๋ฐฐ: ํจ์จ์ ์ธ ๋ถํ ๊ท ํ์ ์ํด ์ค๋ ๋๋น 2๊ฐ ์์ ์ฒ๋ฆฌ
- ์ถ๋ ฅ:
input_shared[256]์ ์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์ฑ์ฐ๊ธฐ
-
Stage 2 ์ค๋ ๋:
STAGE2_THREADS = 128(์ค๋ ๋ 128-255, ๋ธ๋ก์ ํ๋ฐ๋ถ)- ์ญํ : ์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ์ ์ํ ๋ธ๋ฌ ํํฐ ์ ์ฉ
- ์์ ๋ถ๋ฐฐ: ์ค๋ ๋๋น 2๊ฐ์ ๋ธ๋ฌ ์ฐ์ฐ ์ฒ๋ฆฌ
- ์ถ๋ ฅ:
blur_shared[256]์ ๋ธ๋ฌ ๊ฒฐ๊ณผ ์ฑ์ฐ๊ธฐ
-
Stage 3 ์ค๋ ๋: ์ ์ฒด 256๊ฐ ์ค๋ ๋ ํ๋ ฅ
- ์ญํ : ์ต์ข ์ค๋ฌด๋ฉ ๋ฐ ์ ์ญ ๋ฉ๋ชจ๋ฆฌ๋ก ์ถ๋ ฅ
- ์์
๋ถ๋ฐฐ: ์ผ๋์ผ ๋งคํ (์ค๋ ๋
i๊ฐ ์์i๋ฅผ ์ฒ๋ฆฌ) - ์ถ๋ ฅ: ๊ธ๋ก๋ฒ
output๋ฐฐ์ด์ ์ต์ข ๊ฒฐ๊ณผ ๊ธฐ๋ก
์์ฑํ ์ฝ๋
comptime TPB = 256 # Threads per block for pipeline stages
comptime SIZE = 1024 # Image size (1D for simplicity)
comptime BLOCKS_PER_GRID = (4, 1)
comptime THREADS_PER_BLOCK = (TPB, 1)
comptime dtype = DType.float32
comptime layout = row_major[SIZE]()
comptime LayoutType = type_of(layout)
# Multi-stage processing configuration
comptime STAGE1_THREADS = TPB // 2
comptime STAGE2_THREADS = TPB // 2
comptime BLUR_RADIUS = 2
def multi_stage_image_blur_pipeline(
output: TileTensor[mut=True, dtype, LayoutType, MutAnyOrigin],
input: TileTensor[mut=False, dtype, LayoutType, ImmutAnyOrigin],
size: Int,
):
"""Multi-stage image blur pipeline with barrier coordination.
Stage 1 (threads 0-127): Load input data and apply 1.1x preprocessing
Stage 2 (threads 128-255): Apply 5-point blur with BLUR_RADIUS=2
Stage 3 (all threads): Final neighbor smoothing and output
"""
# Shared memory buffers for pipeline stages
var input_shared = stack_allocation[
dtype=dtype, address_space=AddressSpace.SHARED
](row_major[TPB]())
var blur_shared = stack_allocation[
dtype=dtype, address_space=AddressSpace.SHARED
](row_major[TPB]())
var global_i = block_dim.x * block_idx.x + thread_idx.x
var local_i = thread_idx.x
# Stage 1: Load and preprocess (threads 0-127)
# FILL ME IN (roughly 10 lines)
barrier() # Wait for Stage 1 completion
# Stage 2: Apply blur (threads 128-255)
# FILL ME IN (roughly 25 lines)
barrier() # Wait for Stage 2 completion
# Stage 3: Final smoothing (all threads)
# FILL ME IN (roughly 7 lines)
barrier() # Ensure all writes complete
์ ์ฒด ํ์ผ ๋ณด๊ธฐ: problems/p29/p29.mojo
ํ
์ค๋ ๋ ์ญํ ์๋ณ
- ์ค๋ ๋ ์ธ๋ฑ์ค ๋น๊ต๋ฅผ ํตํด ๊ฐ ์ค๋ ๋๊ฐ ์ด๋ค ๋จ๊ณ๋ฅผ ์คํํด์ผ ํ๋์ง ๊ฒฐ์
- Stage 1: ์ ๋ฐ๋ถ ์ค๋ ๋ (์ค๋ ๋ 0-127)
- Stage 2: ํ๋ฐ๋ถ ์ค๋ ๋ (์ค๋ ๋ 128-255)
- Stage 3: ๋ชจ๋ ์ค๋ ๋ ์ฐธ์ฌ
Stage 1 ์ ๊ทผ ๋ฐฉ์
- ์ ์ ํ ์ธ๋ฑ์ค ๋น๊ต๋ฅผ ํตํด Stage 1 ์ค๋ ๋ ์๋ณ
- ๋ถํ ๊ท ํ์ ์ํด ๊ฐ ์ค๋ ๋๊ฐ ์ฌ๋ฌ ์์๋ฅผ ์ฒ๋ฆฌ
- ์ ์ฒ๋ฆฌ ๊ฐํ ๊ณ์ ์ ์ฉ
- ์ ๋ก ํจ๋ฉ์ ์ฌ์ฉํ ์ ์ ํ ๊ฒฝ๊ณ ์ฒ๋ฆฌ ๊ตฌํ
Stage 2 ์ ๊ทผ ๋ฐฉ์
- Stage 2 ์ค๋ ๋๋ฅผ ์๋ณํ๊ณ ์ธ๋ฑ์ค๋ฅผ ์ฒ๋ฆฌ ๋ฒ์์ ๋งคํ
- ์ด์ ์์์ ํ๊ท ์ ๊ตฌํ๋ ๋ธ๋ฌ ์ปค๋ ๊ตฌํ
- ์ ํจํ ์ด์๋ง ํฌํจํ์ฌ ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒ๋ฆฌ
- ํจ์จ์ฑ์ ์ํด ์ค๋ ๋๋น ์ฌ๋ฌ ์์ ์ฒ๋ฆฌ
Stage 3 ์ ๊ทผ ๋ฐฉ์
- ๋ชจ๋ ์ค๋ ๋๊ฐ ์ต์ข ์ฒ๋ฆฌ์ ์ฐธ์ฌ
- ์ง์ ๋ ์ค์ผ์ผ๋ง ๊ณ์๋ฅผ ์ฌ์ฉํ ์ด์ ์ค๋ฌด๋ฉ ์ ์ฉ
- ์ด์์ด ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ์ ์ฃ์ง ์ผ์ด์ค ์ฒ๋ฆฌ
- ๊ฒฝ๊ณ ๊ฒ์ฌ๋ฅผ ํตํด ๊ธ๋ก๋ฒ ์ถ๋ ฅ์ ๊ฒฐ๊ณผ ๊ธฐ๋ก
๋๊ธฐํ ์ ๋ต
- ๊ฒฝ์ ์ํ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋จ๊ณ ์ฌ์ด์ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น
- ์์กดํ๋ ๋จ๊ณ๊ฐ ์์๋๊ธฐ ์ ์ ๊ฐ ๋จ๊ณ๊ฐ ์๋ฃ๋๋๋ก ๋ณด์ฅ
- ๋ธ๋ก ์ข ๋ฃ ์ ์๋ฃ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ต์ข ๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ
์ฝ๋ ์คํ
์๋ฃจ์ ์ ํ ์คํธํ๋ ค๋ฉด ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ ์คํํฉ๋๋ค:
pixi run p29 --multi-stage
pixi run -e amd p29 --multi-stage
uv run poe p29 --multi-stage
ํผ์ฆ์ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃํ๋ฉด ๋ค์๊ณผ ์ ์ฌํ ์ถ๋ ฅ์ด ํ์๋ฉ๋๋ค:
Puzzle 29: GPU Synchronization Primitives
==================================================
TPB: 256
SIZE: 1024
STAGE1_THREADS: 128
STAGE2_THREADS: 128
BLUR_RADIUS: 2
Testing Puzzle 29A: Multi-Stage Pipeline Coordination
============================================================
Multi-stage pipeline blur completed
Input sample: 0.0 1.01 2.02
Output sample: 1.6665002 2.3331003 3.3996604
โ
Multi-stage pipeline coordination test PASSED!
์๋ฃจ์
def multi_stage_image_blur_pipeline(
output: TileTensor[mut=True, dtype, LayoutType, MutAnyOrigin],
input: TileTensor[mut=False, dtype, LayoutType, MutAnyOrigin],
size: Int,
):
"""Multi-stage image blur pipeline with barrier coordination.
Stage 1 (threads 0-127): Load input data and apply 1.1x preprocessing
Stage 2 (threads 128-255): Apply 5-point blur with BLUR_RADIUS=2
Stage 3 (all threads): Final neighbor smoothing and output
"""
# Shared memory buffers for pipeline stages
var input_shared = stack_allocation[
dtype=dtype, address_space=AddressSpace.SHARED
](row_major[TPB]())
var blur_shared = stack_allocation[
dtype=dtype, address_space=AddressSpace.SHARED
](row_major[TPB]())
var global_i = block_dim.x * block_idx.x + thread_idx.x
var local_i = thread_idx.x
# Stage 1: Load and preprocess (threads 0-127)
if local_i < STAGE1_THREADS:
if global_i < size:
input_shared[local_i] = input[global_i] * 1.1
# Each thread loads 2 elements
if local_i + STAGE1_THREADS < size:
input_shared[local_i + STAGE1_THREADS] = (
input[global_i + STAGE1_THREADS] * 1.1
)
else:
# Zero-padding for out-of-bounds
input_shared[local_i] = 0.0
if local_i + STAGE1_THREADS < TPB:
input_shared[local_i + STAGE1_THREADS] = 0.0
barrier() # Wait for Stage 1 completion
# Stage 2: Apply blur (threads 128-255)
if local_i >= STAGE1_THREADS:
var blur_idx = local_i - STAGE1_THREADS
var blur_sum: Scalar[dtype] = 0.0
blur_count = 0
# 5-point blur kernel
for offset in range(-BLUR_RADIUS, BLUR_RADIUS + 1):
sample_idx = blur_idx + offset
if sample_idx >= 0 and sample_idx < TPB:
blur_sum += rebind[Scalar[dtype]](input_shared[sample_idx])
blur_count += 1
if blur_count > 0:
blur_shared[blur_idx] = blur_sum / Scalar[dtype](blur_count)
else:
blur_shared[blur_idx] = 0.0
# Process second element
var second_idx = blur_idx + STAGE1_THREADS
if second_idx < TPB:
blur_sum = 0.0
blur_count = 0
for offset in range(-BLUR_RADIUS, BLUR_RADIUS + 1):
sample_idx = second_idx + offset
if sample_idx >= 0 and sample_idx < TPB:
blur_sum += rebind[Scalar[dtype]](input_shared[sample_idx])
blur_count += 1
if blur_count > 0:
blur_shared[second_idx] = blur_sum / Scalar[dtype](blur_count)
else:
blur_shared[second_idx] = 0.0
barrier() # Wait for Stage 2 completion
# Stage 3: Final smoothing (all threads)
if global_i < size:
final_value = blur_shared[local_i]
# Neighbor smoothing with 0.6 scaling
if local_i > 0:
final_value = (final_value + blur_shared[local_i - 1]) * 0.6
if local_i < TPB - 1:
final_value = (final_value + blur_shared[local_i + 1]) * 0.6
output[global_i] = final_value
barrier() # Ensure all writes complete
ํต์ฌ ํต์ฐฐ์ ์ด๊ฒ์ด ์ค๋ ๋ ์ญํ ํนํ๋ฅผ ๊ฐ์ง ํ์ดํ๋ผ์ธ ์ํคํ ์ฒ ๋ฌธ์ ์์ ์ธ์ํ๋ ๊ฒ์ ๋๋ค:
- ๋จ๊ณ๋ณ ์ค๋ ๋ ๊ทธ๋ฃน ์ค๊ณ: ๋ฐ์ดํฐ๋ฟ๋ง ์๋๋ผ ๊ธฐ๋ฅ๋ณ๋ก ์ค๋ ๋๋ฅผ ๋ถํ
- ์์ฐ์-์๋น์ ์ฒด์ธ ๊ตฌํ: Stage 1์ด Stage 2๋ฅผ ์ํด ์์ฐํ๊ณ , Stage 2๊ฐ Stage 3์ ์ํด ์์ฐ
- ์ ๋ต์ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น: ๋์ผํ ์๊ณ ๋ฆฌ์ฆ ๋ด๊ฐ ์๋๋ผ ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์ ๋๊ธฐํ
- ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด ์ต์ ํ: ๋ณํฉ๋ ์ฝ๊ธฐ์ ํจ์จ์ ์ธ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ๋ณด์ฅ
์์ธ ์ค๋ช ์ด ํฌํจ๋ ์ ์ฒด ์๋ฃจ์
๋ค๋จ๊ณ ํ์ดํ๋ผ์ธ ์๋ฃจ์ ์ ์ ๊ตํ ์ค๋ ๋ ํนํ์ ๋ฐฐ๋ฆฌ์ด ์กฐ์ ์ ๋ณด์ฌ์ค๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ ํต์ ์ธ ๋จ์ผ์ฒด์ GPU ์๊ณ ๋ฆฌ์ฆ์ ํนํ๋๊ณ ์กฐ์จ๋ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ณํํฉ๋๋ค.
ํ์ดํ๋ผ์ธ ์ํคํ ์ฒ ์ค๊ณ
์ด ํผ์ฆ์ ๊ทผ๋ณธ์ ์ธ ๋ํ๊ตฌ๋ ๋ฐ์ดํฐ๊ฐ ์๋ ์ญํ ์ ์ํ ์ค๋ ๋ ํนํ์ ๋๋ค:
์ ํต์ ์ธ ์ ๊ทผ ๋ฐฉ์: ๋ชจ๋ ์ค๋ ๋๊ฐ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ์ ๋ํด ๋์ผํ ์๊ณ ๋ฆฌ์ฆ์ ์คํ
- ๋ชจ๋ ์ค๋ ๋๊ฐ ๋์ผํ ์ฐ์ฐ์ ์ํ (๋ฆฌ๋์ ์ด๋ ํ๋ ฌ ์ฐ์ฐ ๋ฑ)
- ๋ฐฐ๋ฆฌ์ด๋ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ ๋จ๊ณ ๋ด์์ ์ค๋ ๋๋ฅผ ๋๊ธฐํ
- ์ค๋ ๋ ์ญํ ์ ์ฒ๋ฆฌํ๋ ๋ฐ์ดํฐ ์ธ๋ฑ์ค๋ง ๋ค๋ฆ
์ด ํผ์ฆ์ ํ์ : ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์์ ํ ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํ
- ์ค๋ ๋ 0-127์ด ๋ก๋ฉ ๋ฐ ์ ์ฒ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ์คํ
- ์ค๋ ๋ 128-255๊ฐ ๋ธ๋ฌ ์ฒ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ์คํ
- ๋ชจ๋ ์ค๋ ๋๊ฐ ์ต์ข ์ค๋ฌด๋ฉ ์๊ณ ๋ฆฌ์ฆ์ ํ๋ ฅ
- ๋ฐฐ๋ฆฌ์ด๋ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ ๋ด๊ฐ ์๋๋ผ ์๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์ ์กฐ์จ
์์ฐ์-์๋น์ ์กฐ์
์ค๋ ๋๊ฐ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ ๋ด์์ ๋๋ฑํ ์ญํ ์ ํ๋ ์ด์ ํผ์ฆ๊ณผ ๋ฌ๋ฆฌ, ์ด ํผ์ฆ์ ๋ช ์์ ์ธ ์์ฐ์-์๋น์ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค:
- Stage 1: ์์ฐ์ (Stage 2๋ฅผ ์ํ ์ ์ฒ๋ฆฌ ๋ฐ์ดํฐ ์์ฑ)
- Stage 2: ์๋น์ (Stage 1์ ๋ฐ์ดํฐ ์ฌ์ฉ) + ์์ฐ์ (Stage 3์ ์ํ ๋ธ๋ฌ ๋ฐ์ดํฐ ์์ฑ)
- Stage 3: ์๋น์ (Stage 2์ ๋ฐ์ดํฐ ์ฌ์ฉ)
์ ๋ต์ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น
๋ฐฐ๋ฆฌ์ด๊ฐ ์ธ์ ํ์ํ๊ณ ์ธ์ ๋ญ๋น์ ์ธ์ง ์ดํดํ๊ธฐ:
- ํ์ํ ๊ฒฝ์ฐ: ์์กด์ ์ธ ๋จ๊ณ ์ฌ์ด์์ ๊ฒฝ์ ์ํ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด
- ๋ญ๋น์ ์ธ ๊ฒฝ์ฐ: ๊ฐ์ ๋จ๊ณ์ ๋ ๋ฆฝ์ ์ธ ์ฐ์ฐ ๋ด์์
- ์ฑ๋ฅ ํต์ฐฐ: ๊ฐ ๋ฐฐ๋ฆฌ์ด์๋ ๋น์ฉ์ด ์์ผ๋ฏ๋ก ์ ๋ต์ ์ผ๋ก ์ฌ์ฉ
ํต์ฌ ๋๊ธฐํ ์ง์ :
- Stage 1 ์ดํ: Stage 2๊ฐ ๋ถ์์ ํ ์ ์ฒ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒ์ ๋ฐฉ์ง
- Stage 2 ์ดํ: Stage 3์ด ๋ถ์์ ํ ๋ธ๋ฌ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๋ ๊ฒ์ ๋ฐฉ์ง
- Stage 3 ์ดํ: ๋ธ๋ก ์ข ๋ฃ ์ ๋ชจ๋ ์ถ๋ ฅ ์ฐ๊ธฐ๊ฐ ์๋ฃ๋๋๋ก ๋ณด์ฅ
์ค๋ ๋ ํ์ฉ ํจํด
- Stage 1: 50% ํ์ฉ (256๊ฐ ์ค 128๊ฐ ์ค๋ ๋ ํ์ฑ, 128๊ฐ ์ ํด)
- Stage 2: 50% ํ์ฉ (128๊ฐ ํ์ฑ, 128๊ฐ ์ ํด)
- Stage 3: 100% ํ์ฉ (์ ์ฒด 256๊ฐ ์ค๋ ๋ ํ์ฑ)
์ด๊ฒ์ ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์กฐ์จ๋ ํ์ดํ๋ผ์ธ ๋ด์์ ์๋ก ๋ค๋ฅธ ์ฐ์ฐ ์์ ์ ํนํ๋๋ ์ ๊ตํ ์๊ณ ๋ฆฌ์ฆ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๋ณด์ฌ์ฃผ๋ฉฐ, ๋จ์ํ ๋ฐ์ดํฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๋์ด ์ค์ GPU ์๊ณ ๋ฆฌ์ฆ์ ํ์ํ ์ํคํ ์ฒ์ ์ฌ๊ณ ๋ก ๋์๊ฐ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ ์ต์ ํ
๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ํคํ ์ฒ:
- ๋ ๊ฐ์ ํนํ๋ ๋ฒํผ๊ฐ ๋จ๊ณ ๊ฐ ๋ฐ์ดํฐ ํ๋ฆ์ ์ฒ๋ฆฌ
- ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ๊ฒฝ๊ณ ์ฐ์ฐ์๋ง ์ต์ํ
- ๋ชจ๋ ์ค๊ฐ ์ฒ๋ฆฌ์ ๋น ๋ฅธ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ
์ ๊ทผ ํจํด์ ์ด์ :
- Stage 1: ์ ๋ ฅ ๋ก๋ฉ์ ์ํ ๋ณํฉ๋ ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ
- Stage 2: ๋ธ๋ฌ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋น ๋ฅธ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ
- Stage 3: ์ถ๋ ฅ์ ์ํ ๋ณํฉ๋ ์ ์ญ ๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ
์ค์ ์์ฉ ๋ถ์ผ
์ด ํ์ดํ๋ผ์ธ ์ํคํ ์ฒ ํจํด์ ๋ค์ ๋ถ์ผ์ ๊ธฐ๋ฐ์ด ๋ฉ๋๋ค:
์ด๋ฏธ์ง ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ:
- ๋ค๋จ๊ณ ํํฐ (๋ธ๋ฌ, ์ ๋ช ํ, ์ฃ์ง ๊ฒ์ถ์ ์์ฐจ์ ์ผ๋ก)
- ์ ๊ณต๊ฐ ๋ณํ (RGB โ HSV โ ์ฒ๋ฆฌ โ RGB)
- ๋ค์ค ์๊ณ ๋ฆฌ์ฆ ํจ์ค๋ฅผ ์ฌ์ฉํ ๋ ธ์ด์ฆ ๊ฐ์
๊ณผํ ์ฐ์ฐ:
- ๋ค๋จ๊ณ ์ ํ ์ฐจ๋ถ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์คํ ์ค ์ฐ์ฐ
- ํํฐ๋ง, ๋ณํ, ๋ถ์ ํ์ดํ๋ผ์ธ์ ์ฌ์ฉํ ์ ํธ ์ฒ๋ฆฌ
- ๋ค๋จ๊ณ ์๋ฒ ๋ฐ๋ณต์ ์ฌ์ฉํ ์ ์ฐ ์ ์ฒด ์ญํ
๋จธ์ ๋ฌ๋:
- ์๋ก ๋ค๋ฅธ ์ฐ์ฐ์ ์ํด ํนํ๋ ์ค๋ ๋ ๊ทธ๋ฃน์ ๊ฐ์ง ์ ๊ฒฝ๋ง ๋ ์ด์ด
- ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ (์กฐ์จ๋ ๋จ๊ณ์์ ๋ก๋, ์ ๊ทํ, ์ฆ๊ฐ)
- ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ทธ๋ฃน์ด ์๋ก ๋ค๋ฅธ ์ฐ์ฐ์ ์ฒ๋ฆฌํ๋ ๋ฐฐ์น ์ฒ๋ฆฌ
ํต์ฌ ๊ธฐ์ ์ ํต์ฐฐ
์๊ณ ๋ฆฌ์ฆ ๋ณ๋ ฌ ์ฒ๋ฆฌ vs. ๋ฐ์ดํฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ:
- ๋ฐ์ดํฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ: ์ค๋ ๋๊ฐ ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ ์์์ ๋์ผํ ์ฝ๋๋ฅผ ์คํ
- ์๊ณ ๋ฆฌ์ฆ ๋ณ๋ ฌ ์ฒ๋ฆฌ: ์ค๋ ๋๊ฐ ํนํ๋ ์ญํ ์ ๋ฐ๋ผ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์คํ
๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ ์ฒ ํ:
- ์ ๋ต์ ๋ฐฐ์น: ์์กด์ ์ธ ๋จ๊ณ ๊ฐ์ ๊ฒฝ์ ์ํ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ํ์ํ ๊ณณ์๋ง ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น
- ์ฑ๋ฅ ๊ณ ๋ ค์ฌํญ: ๊ฐ ๋ฐฐ๋ฆฌ์ด์๋ ๋๊ธฐํ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๋ฏ๋ก ์ ํํ์ง๋ง ์ ์ ๋ ์ฌ์ฉ
- ์ ํ์ฑ ๋ณด์ฅ: ์ ์ ํ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น๋ก ์ค๋ ๋ ์คํ ํ์ด๋ฐ์ ๊ด๊ณ์์ด ๊ฒฐ์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅ
์ค๋ ๋ ํนํ์ ์ด์ :
- ์๊ณ ๋ฆฌ์ฆ ์ต์ ํ: ๊ฐ ๋จ๊ณ๋ฅผ ํด๋น ์ฐ์ฐ ํจํด์ ๋ง๊ฒ ์ต์ ํ ๊ฐ๋ฅ
- ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์ต์ ํ: ์๋ก ๋ค๋ฅธ ๋จ๊ณ์์ ์๋ก ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์ ๋ต ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ฆฌ์์ค ํ์ฉ: ๋ณต์กํ ์๊ณ ๋ฆฌ์ฆ์ ํนํ๋๊ณ ํจ์จ์ ์ธ ๊ตฌ์ฑ ์์๋ก ๋ถํด ๊ฐ๋ฅ
์ด ์๋ฃจ์ ์ ๋ณต์กํ ๋ค๋จ๊ณ ์ฐ์ฐ์ ์ํด ์ค๋ ๋ ํนํ์ ์ ๋ต์ ๋๊ธฐํ๋ฅผ ํ์ฉํ๋ ์ ๊ตํ GPU ์๊ณ ๋ฆฌ์ฆ์ ์ค๊ณํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ฉฐ, ๋จ์ํ ๋ณ๋ ฌ ๋ฃจํ๋ฅผ ๋์ด ์ค์ GPU ์ํํธ์จ์ด์์ ์ฌ์ฉ๋๋ ์ํคํ ์ฒ์ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๋์๊ฐ๋๋ค.