๐ ๊ฒฝ์ ์ํ ๋๋ฒ๊น
๊ฐ์
NVIDIA compute-sanitizer๋ฅผ ์ฌ์ฉํด ์๋ชป๋ ๊ฒฐ๊ณผ๋ฅผ ์ผ์ผํค๋ ๊ฒฝ์ ์ํ๋ฅผ ์๋ณํ๋ฉด์ ์คํจํ๋ GPU ํ๋ก๊ทธ๋จ์ ๋๋ฒ๊น
ํฉ๋๋ค. ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฐ์ฐ์์ ๋์์ฑ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ racecheck ๋๊ตฌ ์ฌ์ฉ๋ฒ์ ๋ฐฐ์๋๋ค.
๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ก ์ฌ๋ฌ ์ค๋ ๋์ ๊ฐ์ ๋์ ํด์ผ ํ๋ GPU ์ปค๋์ด ์์ต๋๋ค. ํ ์คํธ๋ ์คํจํ๋๋ฐ, ๋ก์ง์ ์ฌ๋ฐ๋ฅธ ๊ฒ ๊ฐ์ต๋๋ค. ๋น์ ์ ๊ณผ์ ๋ ์คํจ๋ฅผ ์ผ์ผํค๋ ๊ฒฝ์ ์ํ๋ฅผ ์ฐพ์ ์์ ํ๋ ๊ฒ์ ๋๋ค.
๊ตฌ์ฑ
comptime SIZE = 2
comptime BLOCKS_PER_GRID = 1
comptime THREADS_PER_BLOCK = (3, 3) # 9๊ฐ ์ค๋ ๋ ์ค 4๊ฐ๋ง ํ์ฑํ
comptime dtype = DType.float32
์คํจํ๋ ์ปค๋
comptime SIZE = 2
comptime BLOCKS_PER_GRID = 1
comptime THREADS_PER_BLOCK = (3, 3)
comptime dtype = DType.float32
comptime layout = Layout.row_major(SIZE, SIZE)
fn shared_memory_race(
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: UInt,
):
row = thread_idx.y
col = thread_idx.x
shared_sum = LayoutTensor[
dtype,
Layout.row_major(1),
MutAnyOrigin,
address_space = AddressSpace.SHARED,
].stack_allocation()
if row < size and col < size:
shared_sum[0] += a[row, col]
barrier()
if row < size and col < size:
output[row, col] = shared_sum[0]
์ ์ฒด ํ์ผ ๋ณด๊ธฐ: problems/p10/p10.mojo
์ฝ๋ ์คํ
pixi run p10 --race-condition
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
out shape: 2 x 2
Running race condition example...
out: HostBuffer([0.0, 0.0, 0.0, 0.0])
expected: HostBuffer([6.0, 6.0, 6.0, 6.0])
stack trace was not collected. Enable stack trace collection with environment variable `MOJO_ENABLE_STACK_TRACE_ON_ERROR`
Unhandled exception caught during execution: At /home/ubuntu/workspace/mojo-gpu-puzzles/problems/p10/p10.mojo:122:33: AssertionError: `left == right` comparison failed:
left: 0.0
right: 6.0
compute-sanitizer๊ฐ GPU ์ฝ๋์ ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ์ฐพ์๋ด๋์ง ์ดํด๋ด
์๋ค.
compute-sanitizer๋ก ๋๋ฒ๊น
ํ๊ธฐ
1๋จ๊ณ: racecheck๋ก ๊ฒฝ์ ์ํ ์๋ณ
compute-sanitizer์ racecheck ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฝ์ ์ํ๋ฅผ ์๋ณํฉ๋๋ค:
pixi run compute-sanitizer --tool racecheck mojo problems/p10/p10.mojo --race-condition
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
========= COMPUTE-SANITIZER
out shape: 2 x 2
Running race condition example...
========= Error: Race reported between Write access at p10_shared_memory_race_...+0x140
========= and Read access at p10_shared_memory_race_...+0xe0 [4 hazards]
========= and Write access at p10_shared_memory_race_...+0x140 [5 hazards]
=========
out: HostBuffer([0.0, 0.0, 0.0, 0.0])
expected: HostBuffer([6.0, 6.0, 6.0, 6.0])
AssertionError: `left == right` comparison failed:
left: 0.0
right: 6.0
========= RACECHECK SUMMARY: 1 hazard displayed (1 error, 0 warnings)
๋ถ์: ํ๋ก๊ทธ๋จ์ 1๊ฐ์ ๊ฒฝ์ ์ํ์ 9๊ฐ์ ๊ฐ๋ณ ์ํ ์์๊ฐ ์์ต๋๋ค:
- 4๊ฐ์ read-after-write ์ํ ์์ (๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ฐ๋ ๋์ ์ฝ๊ธฐ)
- 5๊ฐ์ write-after-write ์ํ ์์ (์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์ฐ๊ธฐ)
2๋จ๊ณ: synccheck์ ๋น๊ต
๋๊ธฐํ ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ ์ํ์ธ์ง ํ์ธํฉ๋๋ค:
pixi run compute-sanitizer --tool synccheck mojo problems/p10/p10.mojo --race-condition
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
========= COMPUTE-SANITIZER
out shape: 2 x 2
Running race condition example...
out: HostBuffer([0.0, 0.0, 0.0, 0.0])
expected: HostBuffer([6.0, 6.0, 6.0, 6.0])
AssertionError: `left == right` comparison failed:
left: 0.0
right: 6.0
========= ERROR SUMMARY: 0 errors
ํต์ฌ ํต์ฐฐ: synccheck๊ฐ 0๊ฐ์ ์ค๋ฅ๋ฅผ ์ฐพ์์ต๋๋ค - ๊ต์ฐฉ ์ํ ๊ฐ์ ๋๊ธฐํ ๋ฌธ์ ๋ ์์ต๋๋ค. ๋ฌธ์ ๋ ๋๊ธฐํ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒฝ์ ์ํ์
๋๋ค.
๊ต์ฐฉ ์ํ vs ๊ฒฝ์ ์ํ: ์ฐจ์ด์ ์ดํดํ๊ธฐ
| ์ธก๋ฉด | ๊ต์ฐฉ ์ํ | ๊ฒฝ์ ์ํ |
|---|---|---|
| ์ฆ์ | ํ๋ก๊ทธ๋จ์ด ์์ํ ๋ฉ์ถค | ํ๋ก๊ทธ๋จ์ด ์๋ชป๋ ๊ฒฐ๊ณผ ์์ฑ |
| ์คํ | ์๋ฃ๋์ง ์์ | ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋จ |
| ํ์ด๋ฐ | ๊ฒฐ์ ์ ์ผ๋ก ๋ฉ์ถค | ๋น๊ฒฐ์ ์ ๊ฒฐ๊ณผ |
| ๊ทผ๋ณธ ์์ธ | ๋๊ธฐํ ๋ก์ง ์ค๋ฅ | ๋๊ธฐํ๋์ง ์์ ๋ฐ์ดํฐ ์ ๊ทผ |
| ํ์ง ๋๊ตฌ | synccheck | racecheck |
| ์์ | Puzzle 09: ์ธ ๋ฒ์งธ ์ฌ๋ก ๋ฐฐ๋ฆฌ์ด ๊ต์ฐฉ ์ํ | ๊ณต์ ๋ฉ๋ชจ๋ฆฌ += ์ฐ์ฐ |
์ฐ๋ฆฌ ์ฌ๋ก์์:
- ํ๋ก๊ทธ๋จ ์๋ฃ๋จ โ ๊ต์ฐฉ ์ํ ์์ (์ค๋ ๋๊ฐ ๋ฉ์ถ์ง ์์)
- ์๋ชป๋ ๊ฒฐ๊ณผ โ ๊ฒฝ์ ์ํ (์ค๋ ๋๋ค์ด ์๋ก์ ๋ฐ์ดํฐ๋ฅผ ์์)
- ๋๊ตฌ ํ์ธ โ
synccheck๋ 0๊ฐ ์ค๋ฅ,racecheck๋ 9๊ฐ ์ํ ์์ ๋ณด๊ณ
๋๋ฒ๊น ์์ ์ด ๊ตฌ๋ถ์ด ์ค์ํ ์ด์ :
- ๊ต์ฐฉ ์ํ ๋๋ฒ๊น : ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น, ์กฐ๊ฑด๋ถ ๋๊ธฐํ, ์ค๋ ๋ ์กฐ์จ์ ์ง์ค
- ๊ฒฝ์ ์ํ ๋๋ฒ๊น : ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด, ์์์ ์ฐ์ฐ (์ญ์ฃผ: ์ค๊ฐ ์ํ ์์ด ์์ ํ ์คํ๋๊ฑฐ๋ ์ ํ ์คํ๋์ง ์๋ ์ฐ์ฐ), ๋ฐ์ดํฐ ์์กด์ฑ์ ์ง์ค
๋์ ๊ณผ์
์ด ๋๊ตฌ๋ค์ ํ์ฉํ์ฌ ์คํจํ๋ ์ปค๋์ ์์ ํ์ธ์.
ํ
์ํ ์์ ๋ถ์
shared_sum[0] += a[row, col] ์ฐ์ฐ์ด ์ํํ ์ด์ ๋ ์ค์ ๋ก ์ธ ๊ฐ์ ๋ณ๋ ๋ฉ๋ชจ๋ฆฌ ์ฐ์ฐ์ด๊ธฐ ๋๋ฌธ์
๋๋ค:
shared_sum[0]์ฝ๊ธฐ- ์ฝ์ ๊ฐ์
a[row, col]๋ํ๊ธฐ - ๊ฒฐ๊ณผ๋ฅผ
shared_sum[0]์ ๋ค์ ์ฐ๊ธฐ
4๊ฐ์ ํ์ฑ ์ค๋ ๋(์์น (0,0), (0,1), (1,0), (1,1))์์ ์ด ์ฐ์ฐ๋ค์ด ๊ฒน์น ์ ์์ต๋๋ค:
- ์ค๋ ๋ ํ์ด๋ฐ ์ค์ฒฉ โ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ์ด๊ธฐ๊ฐ(0.0)์ ์ฝ์
- ์
๋ฐ์ดํธ ์์ค โ ๊ฐ ์ค๋ ๋๊ฐ
0.0 + ์์ ์_๊ฐ์ ์จ์ ๋ค๋ฅธ ์ค๋ ๋์ ์์ ์ ๋ฎ์ด์ - ๋น์์์ ์ฐ์ฐ โ
+=๋ณตํฉ ๋์ ์ GPU ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์์ ์์์ ์ด์ง ์์ (์ญ์ฃผ: ์คํ ๋์ค ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ผ์ด๋ค ์ ์์ด ์ค๊ฐ ์ํ๊ฐ ๋ ธ์ถ๋จ)
์ ํํ 9๊ฐ์ ์ํ ์์๊ฐ ๋์ค๋ ์ด์ :
- ๊ฐ ์ค๋ ๋๊ฐ read-modify-write๋ฅผ ์๋
- 4๊ฐ ์ค๋ ๋ ร ์ค๋ ๋๋น 2-3๊ฐ ์ํ ์์ = ์ด 9๊ฐ ์ํ ์์
compute-sanitizer๊ฐ ๋ชจ๋ ์ถฉ๋ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์์ ์ถ์
๊ฒฝ์ ์ํ ๋๋ฒ๊น ํ
- ๋ฐ์ดํฐ ๊ฒฝ์์๋ racecheck ์ฌ์ฉ: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ํ ์์์ ๋ฐ์ดํฐ ์์ ํ์ง
- ๊ต์ฐฉ ์ํ์๋ synccheck ์ฌ์ฉ: ๋๊ธฐํ ๋ฒ๊ทธ(๋ฐฐ๋ฆฌ์ด ๋ฌธ์ , ๊ต์ฐฉ ์ํ) ํ์ง
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ์ง์ค: ๊ณต์ ๋ณ์์ ๋ํ ๋๊ธฐํ๋์ง ์์
+=,=์ฐ์ฐ ์ฐพ๊ธฐ - ํจํด ์๋ณ: read-modify-write ์ฐ์ฐ์ด ํํ ๊ฒฝ์ ์ํ ์์ธ
- ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น ํ์ธ: ๋ฐฐ๋ฆฌ์ด๋ ์ถฉ๋ ์ฐ์ฐ ์ด์ ์ ๋ฐฐ์นํด์ผ ํจ, ์ดํ๊ฐ ์๋
๋๋ฒ๊น ์์ ์ด ๊ตฌ๋ถ์ด ์ค์ํ ์ด์ :
- ๊ต์ฐฉ ์ํ ๋๋ฒ๊น : ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น, ์กฐ๊ฑด๋ถ ๋๊ธฐํ, ์ค๋ ๋ ์กฐ์จ์ ์ง์ค
- ๊ฒฝ์ ์ํ ๋๋ฒ๊น : ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด, ์์์ ์ฐ์ฐ, ๋ฐ์ดํฐ ์์กด์ฑ์ ์ง์ค
ํผํด์ผ ํ ํํ ๊ฒฝ์ ์ํ ํจํด:
- ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์น์ ์ฐ๊ธฐ
- ๋๊ธฐํ๋์ง ์์ read-modify-write ์ฐ์ฐ (
+=,++๋ฑ) - ๊ฒฝ์ ์ํ ์ด์ ์ด ์๋ ์ดํ์ ๋ฐฐ๋ฆฌ์ด ๋ฐฐ์น
์๋ฃจ์
comptime SIZE = 2
comptime BLOCKS_PER_GRID = 1
comptime THREADS_PER_BLOCK = (3, 3)
comptime dtype = DType.float32
comptime layout = Layout.row_major(SIZE, SIZE)
fn shared_memory_race(
output: LayoutTensor[dtype, layout, MutAnyOrigin],
a: LayoutTensor[dtype, layout, ImmutAnyOrigin],
size: UInt,
):
"""Fixed: sequential access with barriers eliminates race conditions."""
row = thread_idx.y
col = thread_idx.x
shared_sum = LayoutTensor[
dtype,
Layout.row_major(1),
MutAnyOrigin,
address_space = AddressSpace.SHARED,
].stack_allocation()
# Only thread 0 does all the accumulation work to prevent races
if row == 0 and col == 0:
# Use local accumulation first, then single write to shared memory
local_sum = Scalar[dtype](0.0)
for r in range(size):
for c in range(size):
local_sum += rebind[Scalar[dtype]](a[r, c])
shared_sum[0] = local_sum # Single write operation
barrier() # Ensure thread 0 completes before others read
# All threads read the safely accumulated result after synchronization
if row < size and col < size:
output[row, col] = shared_sum[0]
๋ฌด์์ด ์๋ชป๋์๋์ง ์ดํดํ๊ธฐ
๊ฒฝ์ ์ํ ๋ฌธ์ ํจํด
์๋ ์คํจํ๋ ์ฝ๋์๋ ์ด ํต์ฌ์ ์ธ ์ค์ด ์์์ต๋๋ค:
shared_sum[0] += a[row, col] # ๊ฒฝ์ ์ํ!
์ด ํ ์ค์ด 4๊ฐ์ ์ ํจํ ์ค๋ ๋ ์ฌ์ด์์ ์ฌ๋ฌ ์ํ ์์๋ฅผ ์ผ์ผํต๋๋ค:
- ์ค๋ ๋ (0,0)์ด ์ฝ์
shared_sum[0](๊ฐ: 0.0) - ์ค๋ ๋ (0,1)์ด ์ฝ์
shared_sum[0](๊ฐ: 0.0) โ Read-after-write ์ํ! - ์ค๋ ๋ (0,0)์ด ์
0.0 + 0 - ์ค๋ ๋ (1,0)์ด ์
0.0 + 2โ Write-after-write ์ํ!
ํ ์คํธ๊ฐ ์คํจํ ์ด์
+=์ฐ์ฐ ์ค ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์๋ก์ ์ฐ๊ธฐ๋ฅผ ์์์ํด+=์ฐ์ฐ์ด ์ค๋จ๋์ด ์ ๋ฐ์ดํธ ์์ค ๋ฐ์- ์์ ํฉ๊ณ 6.0 (0+1+2+3)์ด์ง๋ง, ๊ฒฝ์ ์ํ๋ก ์ธํด 0.0์ด ๋จ
barrier()๊ฐ ๋๋ฌด ๋ฆ๊ฒ ์ด - ๊ฒฝ์ ์ํ๊ฐ ์ด๋ฏธ ๋ฐ์ํ ํ
๊ฒฝ์ ์ํ๋?
๊ฒฝ์ ์ํ๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ณต์ ๋ฐ์ดํฐ์ ๋์์ ์ ๊ทผํ๊ณ , ๊ฒฐ๊ณผ๊ฐ ์์ธก ๋ถ๊ฐ๋ฅํ ์ค๋ ๋ ์คํ ํ์ด๋ฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ๋ ๋ฐ์ํฉ๋๋ค.
์ฃผ์ ํน์ฑ:
- ๋น๊ฒฐ์ ์ ๋์: ๊ฐ์ ์ฝ๋๊ฐ ๋ค๋ฅธ ์คํ์์ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ผ ์ ์์
- ํ์ด๋ฐ ์์กด์ : ๊ฒฐ๊ณผ๊ฐ ์ด๋ค ์ค๋ ๋๊ฐ โ๊ฒฝ์์์ ์ด๊ธฐ๋์งโ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง
- ์ฌํํ๊ธฐ ์ด๋ ค์: ํน์ ์กฐ๊ฑด์ด๋ ํ๋์จ์ด์์๋ง ๋ํ๋ ์ ์์
GPU ํน์ ์ ์ํ์ฑ
๋๊ท๋ชจ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ์ํฅ:
- ์ํ ์์ค ์์: ๊ฒฝ์ ์ํ๊ฐ ์ ์ฒด ์ํ(32๊ฐ ์ค๋ ๋)์ ์ํฅ์ ์ค ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ๋ณํฉ ๋ฌธ์ : ๊ฒฝ์์ผ๋ก ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ด ๊นจ์ง ์ ์์
- ์ปค๋ ์ ์ฒด ์คํจ: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์์์ด ์ ์ฒด GPU ์ปค๋์ ์ํฅ์ ์ค ์ ์์
ํ๋์จ์ด ์ฐจ์ด:
- ๋ค๋ฅธ GPU ์ํคํ ์ฒ: ๊ฒฝ์ ์ํ๊ฐ GPU ๋ชจ๋ธ๋ง๋ค ๋ค๋ฅด๊ฒ ๋ํ๋ ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต: L1 ์บ์, L2 ์บ์, ์ ์ญ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฐ๊ฐ ๋ค๋ฅธ ๊ฒฝ์ ๋์์ ๋ณด์ผ ์ ์์
- ์ํ ์ค์ผ์ค๋ง: ๋ค๋ฅธ ์ค๋ ๋ ์ค์ผ์ค๋ง์ด ๋ค๋ฅธ ๊ฒฝ์ ์ํ ์๋๋ฆฌ์ค๋ฅผ ๋ ธ์ถ์ํฌ ์ ์์
์ ๋ต: ๋จ์ผ ์ฐ๊ธฐ ํจํด
ํต์ฌ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ๋ํ ๋์ ์ฐ๊ธฐ๋ฅผ ์์ ๋ ๊ฒ์ ๋๋ค:
- Single writer: ํ๋์ ์ค๋ ๋(์์น (0,0))๋ง ๋ชจ๋ ๋์ ์์ ์ํ
- ๋ก์ปฌ ๋์ : ์์น (0,0) ์ค๋ ๋๊ฐ ๋ก์ปฌ ๋ณ์๋ฅผ ์ฌ์ฉํด ๋ฐ๋ณต์ ์ธ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ํผํจ
- ๋จ์ผ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ: ๋จ์ผ ์ฐ๊ธฐ ์ฐ์ฐ์ผ๋ก write-write ๊ฒฝ์ ์ ๊ฑฐ
- ๋ฐฐ๋ฆฌ์ด ๋๊ธฐํ: writer๊ฐ ์๋ฃ๋ ํ์์ผ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ฝ๋๋ก ๋ณด์ฅ
- ๋ค์ค ์ฝ๊ธฐ: ๋ชจ๋ ์ค๋ ๋๊ฐ ์์ ํ๊ฒ ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ฝ์
๋จ๊ณ๋ณ ์๋ฃจ์ ๋ถ์
1๋จ๊ณ: ์ค๋ ๋ ์๋ณ
if row == 0 and col == 0:
์ง์ ์ขํ ๊ฒ์ฌ๋ก ์์น (0,0)์ ์ค๋ ๋๋ฅผ ์๋ณํฉ๋๋ค.
2๋จ๊ณ: ๋จ์ผ ์ค๋ ๋ ๋์
if row == 0 and col == 0:
local_sum = Scalar[dtype](0.0)
for r in range(size):
for c in range(size):
local_sum += rebind[Scalar[dtype]](a[r, c])
shared_sum[0] = local_sum # ๋จ์ผ ์ฐ๊ธฐ ์ฐ์ฐ
์์น (0,0)์ ์ค๋ ๋๋ง ๋ชจ๋ ๋์ ์์ ์ ์ํํ์ฌ ๊ฒฝ์ ์ํ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
3๋จ๊ณ: ๋๊ธฐํ ๋ฐฐ๋ฆฌ์ด
barrier() # ์ค๋ ๋ (0,0)์ด ์๋ฃํ ํ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ฝ๋๋ก ๋ณด์ฅ
๋ชจ๋ ์ค๋ ๋๊ฐ ์์น (0,0)์ ์ค๋ ๋๊ฐ ๋์ ์ ๋ง์น ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
4๋จ๊ณ: ์์ ํ ๋ณ๋ ฌ ์ฝ๊ธฐ
if row < size and col < size:
output[row, col] = shared_sum[0]
๋๊ธฐํ ํ ๋ชจ๋ ์ค๋ ๋๊ฐ ์์ ํ๊ฒ ๊ฒฐ๊ณผ๋ฅผ ์ฝ์ ์ ์์ต๋๋ค.
ํจ์จ์ฑ์ ๊ดํ ์ค์ ์ฌํญ
์ด ์๋ฃจ์ ์ ํจ์จ์ฑ๋ณด๋ค ์ ํ์ฑ์ ์ฐ์ ํฉ๋๋ค. ๊ฒฝ์ ์ํ๋ ์ ๊ฑฐํ์ง๋ง, ์์น (0,0) ์ค๋ ๋๋ง ๋์ ์ ์ฌ์ฉํ๋ ๊ฒ์ GPU ์ฑ๋ฅ์ ์ต์ ์ด ์๋๋๋ค - ๋๊ท๋ชจ ๋ณ๋ ฌ ์ฅ์น์์ ์ฌ์ค์ ์ง๋ ฌ ๊ณ์ฐ์ ํ๋ ์ ์ ๋๋ค.
์ด์ด์ Puzzle 11: ํ๋ง์์: ๋ชจ๋ ์ค๋ ๋๋ฅผ ํ์ฉํด ๊ณ ์ฑ๋ฅ ํฉ์ฐ ์ฐ์ฐ์ ์ํํ๋ฉด์๋ ๊ฒฝ์ ์ํ๋ฅผ ํผํ๋ ํจ์จ์ ์ธ ๋ณ๋ ฌ ๋ฆฌ๋์ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐฐ์๋๋ค. ์ด ํผ์ฆ์ ์ ํ์ฑ ์ฐ์ ์ ๊ธฐ์ด๋ฅผ ๊ฐ๋ฅด์นฉ๋๋ค - ๊ฒฝ์ ์ํ๋ฅผ ํผํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๊ณ ๋๋ฉด, Puzzle 11์์ ์ ํ์ฑ๊ณผ ์ฑ๋ฅ ๋ชจ๋๋ฅผ ๋ฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ณด๊ฒ ๋ฉ๋๋ค.
๊ฒ์ฆ
pixi run compute-sanitizer --tool racecheck mojo solutions/p10/p10.mojo --race-condition
์์ ์ถ๋ ฅ:
========= COMPUTE-SANITIZER
out shape: 2 x 2
Running race condition example...
out: HostBuffer([6.0, 6.0, 6.0, 6.0])
expected: HostBuffer([6.0, 6.0, 6.0, 6.0])
โ
Race condition test PASSED! (racecheck will find hazards)
========= RACECHECK SUMMARY: 0 hazards displayed (0 errors, 0 warnings)
โ ์ฑ๊ณต: ํ ์คํธ๊ฐ ํต๊ณผํ๊ณ ๊ฒฝ์ ์ํ๊ฐ ํ์ง๋์ง ์์์ต๋๋ค!