๐ Mojo ๋ฒค์น๋งํน - ์ฑ๋ฅ ๋ถ์๊ณผ ์ต์ ํ
๊ฐ์
์์๋ณ, ํ์ผ๋ง, ์๋ ๋ฒกํฐํ, Mojo vectorize ํจํด์ ํ์ตํ ํ, ์ด์ ์ค์ ์ฑ๋ฅ์ ์ธก์ ํ ์ฐจ๋ก์
๋๋ค. p21.mojo์ ๋ด์ฅ๋ ๋ฒค์น๋งํน ์์คํ
์ ์ฌ์ฉํ์ฌ ์ด๋ฌํ ์ ๊ทผ๋ฒ์ ๊ณผํ์ ์ผ๋ก ๋น๊ตํ๊ณ ์ฑ๋ฅ ํน์ฑ์ ์ดํดํ๋ ๋ฐฉ๋ฒ์ ์์๋ด
๋๋ค.
ํต์ฌ ํต์ฐฐ: ์ด๋ก ์ ๋ถ์์ ๊ฐ์น ์์ง๋ง, ์ค์ฆ์ ๋ฒค์น๋งํน์ด ํน์ ํ๋์จ์ด์์์ ์ค์ ์ฑ๋ฅ์ ๋ณด์ฌ์ค๋๋ค.
๋ฒค์น๋งํฌ ์คํ
์ ์ฒด ๋ฒค์น๋งํฌ๋ฅผ ์คํํ๋ ค๋ฉด:
pixi run p23 --benchmark
pixi run -e amd p23 --benchmark
pixi run -e apple p23 --benchmark
uv run poe p23 --benchmark
๊ฐ ํจํด์ ๋ํ ์ฑ๋ฅ ์ธก์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค:
SIZE: 1024
simd_width: 4
Running P21 GPU Benchmarks...
SIMD width: 4
--------------------------------------------------------------------------------
Testing SIZE=16, TILE=4
Running elementwise_16_4
Running tiled_16_4
Running manual_vectorized_16_4
Running vectorized_16_4
--------------------------------------------------------------------------------
Testing SIZE=128, TILE=16
Running elementwise_128_16
Running tiled_128_16
Running manual_vectorized_128_16
--------------------------------------------------------------------------------
Testing SIZE=128, TILE=16, Vectorize within tiles
Running vectorized_128_16
--------------------------------------------------------------------------------
Testing SIZE=1048576 (1M), TILE=1024
Running elementwise_1M_1024
Running tiled_1M_1024
Running manual_vectorized_1M_1024
Running vectorized_1M_1024
| name | met (ms) | iters |
| ------------------------- | --------------------- | ----- |
| elementwise_16_4 | 0.0033248 | 100 |
| tiled_16_4 | 0.00327392 | 100 |
| manual_vectorized_16_4 | 0.0036169600000000002 | 100 |
| vectorized_16_4 | 0.0037209599999999997 | 100 |
| elementwise_128_16 | 0.00351999 | 100 |
| tiled_128_16 | 0.00370431 | 100 |
| manual_vectorized_128_16 | 0.0043696 | 100 |
| vectorized_128_16 | 0.00378048 | 100 |
| elementwise_1M_1024 | 0.03130143 | 100 |
| tiled_1M_1024 | 0.6892189000000001 | 100 |
| manual_vectorized_1M_1024 | 0.5923888 | 100 |
| vectorized_1M_1024 | 0.1876688 | 100 |
Benchmarks completed!
๋ฒค์น๋งํฌ ์ค์
๋ฒค์น๋งํน ์์คํ
์ Mojo์ ๋ด์ฅ benchmark ๋ชจ๋์ ์ฌ์ฉํฉ๋๋ค:
from benchmark import Bench, BenchConfig, Bencher, BenchId, keep
bench_config = BenchConfig(max_iters=10, num_warmup_iters=1)
max_iters=10: ํต๊ณ์ ์ ๋ขฐ์ฑ์ ์ํด ์ต๋ 10ํ ๋ฐ๋ณตnum_warmup_iters=1: ์ธก์ ์ GPU ์๋ฐ์- Benchmark ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์
๋ฒค์น๋งํน ๊ตฌํ์ ํต์ฌ
ํต์ฌ ์ํฌํ๋ก์ฐ ํจํด
๊ฐ ๋ฒค์น๋งํฌ๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ๊ฒฐํ ํจํด์ ๋ฐ๋ฆ ๋๋ค:
@parameter
fn benchmark_pattern_parameterized[test_size: Int, tile_size: Int](mut b: Bencher) raises:
bench_ctx = DeviceContext()
# ์
์
: ๋ฒํผ ์์ฑ ๋ฐ ๋ฐ์ดํฐ ์ด๊ธฐํ
@parameter
fn pattern_workflow(ctx: DeviceContext) raises:
# ์ฐ์ฐ: ์ธก์ ๋์ ์๊ณ ๋ฆฌ์ฆ ์คํ
b.iter_custom[pattern_workflow](bench_ctx)
# ์ต์ ํ ๋ฐฉ์ง: keep(out.unsafe_ptr())
# ๋๊ธฐํ: ctx.synchronize()
์ฃผ์ ๋จ๊ณ:
- ์ ์ : ๋ฒํผ ํ ๋น ๋ฐ ๋ฐ์ดํฐ ์ด๊ธฐํ
- ์ฐ์ฐ: ๋ฒค์น๋งํฌ ๋์ ์๊ณ ๋ฆฌ์ฆ ์คํ
- ์ต์ ํ ๋ฐฉ์ง: ์ ํํ ์ธก์ ์ ์ํด ํ์
- ๋๊ธฐํ: GPU ์์ ์๋ฃ ํ์ธ
์ค์:
keep()ํจ์keep(out.unsafe_ptr())๋ ์ปดํ์ผ๋ฌ๊ฐ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ฅผ โ์ฌ์ฉ๋์ง ์๋ ์ฝ๋โ๋ก ์ต์ ํํ์ฌ ์ ๊ฑฐํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์ด๊ฒ์ด ์์ผ๋ฉด ์๊ณ ๋ฆฌ์ฆ ๋์ ์๋ฌด๊ฒ๋ ์ธก์ ํ์ง ๋ชปํ ์ ์์ต๋๋ค! GPU ์ปค๋์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๊ธฐ ๋๋ฌธ์ ์ ํํ GPU ๋ฒค์น๋งํน์ ํ์์ ์ ๋๋ค.
์ปค์คํ ๋ฐ๋ณต์ด GPU์ ํ์ํ ์ด์
์ผ๋ฐ์ ์ธ ๋ฒค์น๋งํน์ CPU ์คํ์ผ์ ๋๊ธฐ ์คํ์ ๊ฐ์ ํฉ๋๋ค. GPU ์ปค๋์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ฏ๋ก ๋ค์์ด ํ์ํฉ๋๋ค:
- GPU ์ปจํ ์คํธ ๊ด๋ฆฌ: ์ ์ ํ DeviceContext ์๋ช ์ฃผ๊ธฐ
- ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ: ๋ฐ๋ณต ๊ฐ ๋ฒํผ ์ ๋ฆฌ
- ๋๊ธฐํ ์ฒ๋ฆฌ: ๋น๋๊ธฐ ์ฐ์ฐ์ ์ ํํ ํ์ด๋ฐ
- ์ค๋ฒํค๋ ๋ถ๋ฆฌ: ์ ์ ๋น์ฉ๊ณผ ์ฐ์ฐ ๋น์ฉ์ ๋ถ๋ฆฌ
ํ ์คํธ ์๋๋ฆฌ์ค์ ์ค๋ ๋ ๋ถ์
๋ฒค์น๋งํฌ ๋ชจ์์ ์ฑ๋ฅ ํน์ฑ์ ํ์ ํ๊ธฐ ์ํด ์ธ ๊ฐ์ง ์๋๋ฆฌ์ค๋ฅผ ํ ์คํธํฉ๋๋ค:
์ค๋ ๋ ํ์ฉ ์์ฝ
| ๋ฌธ์ ํฌ๊ธฐ | ํจํด | ์ค๋ ๋ ์ | ์ค๋ ๋๋น SIMD ์ฐ์ฐ | ์ด SIMD ์ฐ์ฐ |
|---|---|---|---|---|
| SIZE=16 | ์์๋ณ | 4 | 1 | 4 |
| ํ์ผ๋ง | 4 | 1 | 4 | |
| ์๋ | 1 | 4 | 4 | |
| vectorize | 4 | 1 | 4 | |
| SIZE=128 | ์์๋ณ | 32 | 1 | 32 |
| ํ์ผ๋ง | 8 | 4 | 32 | |
| ์๋ | 2 | 16 | 32 | |
| vectorize | 8 | 4 | 32 | |
| SIZE=1M | ์์๋ณ | 262,144 | 1 | 262,144 |
| ํ์ผ๋ง | 1,024 | 256 | 262,144 | |
| ์๋ | 256 | 1,024 | 262,144 | |
| vectorize | 1,024 | 256 | 262,144 |
๋ฌธ์ ํฌ๊ธฐ๋ณ ์ฑ๋ฅ ํน์ฑ
์๊ท๋ชจ ๋ฌธ์ (SIZE=16):
- ์คํ ์ค๋ฒํค๋๊ฐ ์ง๋ฐฐ์ (~0.003ms ๊ธฐ์ค์ )
- ์ค๋ ๋ ์ ์ฐจ์ด๋ ๊ฑฐ์ ๋ฌด์๋ฏธ
- ํ์ผ๋ง/vectorize๊ฐ ์ฝ๊ฐ ๋ฎ์ ์ค๋ฒํค๋๋ฅผ ๋ณด์
์ค๊ท๋ชจ ๋ฌธ์ (SIZE=128):
- ์ฌ์ ํ ์ค๋ฒํค๋๊ฐ ์ง๋ฐฐ์ (~0.003ms ์ ํจํด)
- ์ฑ๋ฅ ์ฐจ์ด๊ฐ ๊ฑฐ์ ์ฌ๋ผ์ง
- ์ค๋ฒํค๋ ์ง๋ฐฐ์์ ์ฐ์ฐ ์ง๋ฐฐ๋ก์ ์ ํ ๊ตฌ๊ฐ
๋๊ท๋ชจ ๋ฌธ์ (SIZE=1M):
- ์ค์ง์ ์ธ ์๊ณ ๋ฆฌ์ฆ ์ฐจ์ด๊ฐ ๋๋ฌ๋จ
- ๋น๋ณํฉ ๋ก๋์ ์ํฅ์ด ๋ช ํํด์ง
- ๋๋ ทํ ์ฑ๋ฅ ์์๊ฐ ๋ํ๋จ
๋ฐ์ดํฐ๊ฐ ๋ณด์ฌ์ฃผ๋ ๊ฒ
๋ค์ํ ํ๋์จ์ด์์์ ์ค์ฆ์ ๋ฒค์น๋งํฌ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก:
์ฑ๋ฅ ์์ (๋๊ท๋ชจ ๋ฌธ์ )
| ์์ | ํจํด | ์์ ์๊ฐ | ํต์ฌ ์ธ์ฌ์ดํธ |
|---|---|---|---|
| ๐ฅ | ์์๋ณ | ~0.03ms | ๋ณํฉ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ฐ์ฐ์์ ์น๋ฆฌ |
| ๐ฅ | Mojo vectorize | ~0.19ms | ๋น๋ณํฉ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ์ฑ๋ฅ์ ์ ํ |
| ๐ฅ | ์๋ ๋ฒกํฐํ | ~0.59ms | ๋น๋ณํฉ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ๊ณผ ์๋ ์ต์ ํ๊ฐ ์ฑ๋ฅ ๊ฐ์ |
| 4์ | ํ์ผ๋ง | ~0.69ms | ๋น๋ณํฉ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ, SIMD ๋ก๋ ์๋ ์๋ ์ต์ ํ๊ฐ ์ฑ๋ฅ์ ๋ ์ ํ |
ํต์ฌ ์ฑ๋ฅ ์ธ์ฌ์ดํธ
๋จ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ฐ์ฐ์ ๊ฒฝ์ฐ: ์ต๋ ๋ณ๋ ฌ์ฑ(elementwise)์ด ๋๊ท๋ชจ์์ ๋ณต์กํ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ๋ณด๋ค ์ฐ์ํฉ๋๋ค.
์์๋ณ ํจํด์ด ์น๋ฆฌํ๋ ์ด์ :
- 262,144๊ฐ ์ค๋ ๋๊ฐ ์ฐ์ํ ์ง์ฐ ์๊ฐ ์๋์ ์ ๊ณต
- ๋จ์ํ ๋ฉ๋ชจ๋ฆฌ ํจํด์ด ์ข์ ๋ณํฉ์ ๋ฌ์ฑ
- ์ค๋ ๋๋น ์ต์ํ์ ์ค๋ฒํค๋
- GPU ์ฝ์ด ์์ ๋ฐ๋ผ ์์ฐ์ค๋ฝ๊ฒ ํ์ฅ
ํ์ผ๋ง๊ณผ vectorize๊ฐ ๊ฒฝ์๋ ฅ ์๋ ์ด์ :
- ๋ณ๋ ฌ์ฑ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ง์ญ์ฑ ์ฌ์ด์ ๊ท ํ ์กํ ์ ๊ทผ
- ์๋ ์ต์ ํ(vectorize)๊ฐ ์๋ ํ์ผ๋ง๊ณผ ๊ฑฐ์ ๋๋ฑํ ์ฑ๋ฅ
- ๊ณผ๋ํ ๋ณต์ก๋ ์์ด ์ํธํ ์ค๋ ๋ ํ์ฉ
์๋ ๋ฒกํฐํ๊ฐ ๊ณ ์ ํ๋ ์ด์ :
- 256๊ฐ ์ค๋ ๋๋ง์ผ๋ก๋ ๋ณ๋ ฌ์ฑ์ด ์ ํ์
- ๋ณต์กํ ์ธ๋ฑ์ฑ์ด ์ฐ์ฐ ์ค๋ฒํค๋๋ฅผ ์ถ๊ฐ
- ์ค๋ ๋๋น ๋ํ ์ฒญํฌ๋ก ์ธํ ์บ์ ๋ถ๋ด
- ๋จ์ ์ฐ์ ์์ ํจ๊ณผ ์ฒด๊ฐ
ํ๋ ์์ํฌ ์๋ํ ๊ธฐ๋ฅ:
- ์๋ ๋ฐ๋ณต ํ์ ์กฐ์ (91-100ํ ๋ฐ๋ณต)
- ์๋ก ๋ค๋ฅธ ์คํ ์๊ฐ์ ๊ฑธ์น ํต๊ณ์ ์ ๋ขฐ์ฑ
- ๋ฐ์ด ์ ํ๊ณผ ์์คํ ๋ณ๋์ ๋์
๊ฒฐ๊ณผ ํด์ํ๊ธฐ
์ถ๋ ฅ ํ ์ด๋ธ ์ฝ๊ธฐ
| name | met (ms) | iters |
| elementwise_1M_1024 | 0.03130143 | 100 |
met (ms): ๋จ์ผ ๋ฐ๋ณต์ ์คํ ์๊ฐiters: ์ํ๋ ๋ฐ๋ณต ํ์- ๋์ผ ๋ฌธ์ ํฌ๊ธฐ ๋ด์์ ๋น๊ต: ๊ฐ์ ํฌ๊ธฐ๋ผ๋ฆฌ ๋น๊ตํ๋ ๊ฒ์ด ๊ฐ์ฅ ์๋ฏธ ์์
์ต์ ํ ์์ฌ๊ฒฐ์
์ค์ฆ์ ์ฆ๊ฑฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํจํด์ ์ ํํ์ธ์:
ํ๋ก๋์ ์ํฌ๋ก๋์ ๊ฒฝ์ฐ:
- ๋๊ท๋ชจ ๋ฐ์ดํฐ์ (>100K ์์): ์์๋ณ ํจํด์ด ์ผ๋ฐ์ ์ผ๋ก ์ต์
- ์๊ท๋ชจ/์์ ๋ฐ์ดํฐ์ (<1K ์์): ๋ฎ์ ์ค๋ฒํค๋๋ฅผ ์ํด ํ์ผ๋ง ๋๋ vectorize
- ๊ฐ๋ฐ ์๋ ์ฐ์ : ์๋ ์ต์ ํ๋ฅผ ์ํ Mojo vectorize
- ์๋ ๋ฒกํฐํ ์ง์: ๋จ์ ์ฐ์ฐ์์๋ ๋ณต์ก๋๊ฐ ์ฑ๋ฅ์ผ๋ก ๋ณด์๋๋ ๊ฒฝ์ฐ๊ฐ ๋๋ฌพ
์ฑ๋ฅ ์ต์ ํ ์ํฌํ๋ก์ฐ:
- ๋จผ์ ํ๋กํ์ผ๋ง: ์ต์ ํํ๊ธฐ ์ ์ ์ธก์
- ๋๊ท๋ชจ์์ ํ ์คํธ: ์๊ท๋ชจ ๋ฌธ์ ๋ ์ค์ ์ฑ๋ฅ์ ๋ํด ์คํด๋ฅผ ์ค ์ ์์
- ์ด๋น์ฉ ๊ณ ๋ ค: ๊ฐ๋ฐ ๋ฐ ์ ์ง๋ณด์ ๋ ธ๋ ฅ์ ํฌํจ
- ๊ฐ์ ์ฌํญ ๊ฒ์ฆ: ๋์ ํ๋์จ์ด์์ ๋ฒค์น๋งํฌ๋ก ํ์ธ
๊ณ ๊ธ ๋ฒค์น๋งํน ๊ธฐ๋ฒ
์ปค์คํ ํ ์คํธ ์๋๋ฆฌ์ค
๋งค๊ฐ๋ณ์๋ฅผ ์์ ํ์ฌ ๋ค์ํ ์กฐ๊ฑด์ ํ ์คํธํ ์ ์์ต๋๋ค:
# ๋ค์ํ ๋ฌธ์ ํฌ๊ธฐ
benchmark_elementwise_parameterized[1024, 32] # ๋๊ท๋ชจ ๋ฌธ์
benchmark_elementwise_parameterized[64, 8] # ์๊ท๋ชจ ๋ฌธ์
# ๋ค์ํ ํ์ผ ํฌ๊ธฐ
benchmark_tiled_parameterized[256, 8] # ์์ ํ์ผ
benchmark_tiled_parameterized[256, 64] # ํฐ ํ์ผ
ํ๋์จ์ด ๊ณ ๋ ค ์ฌํญ
๊ฒฐ๊ณผ๋ ๋ค์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค:
- GPU ์ํคํ ์ฒ: SIMD ํญ, ์ฝ์ด ์, ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ
- ์์คํ ๊ตฌ์ฑ: PCIe ๋์ญํญ, CPU ์ฑ๋ฅ
- ์ด ์ํ: GPU ๋ถ์คํธ ํด๋ญ vs ์ง์ ์ฑ๋ฅ
- ๋์ ์ํฌ๋ก๋: GPU ํ์ฉ์ ์ํฅ์ ์ฃผ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค
๋ชจ๋ฒ ์ฌ๋ก ์์ฝ
๋ฒค์น๋งํน ์ํฌํ๋ก์ฐ:
- ์ค์ํ ์ธก์ ์ ์ GPU ์๋ฐ์
- ํต๊ณ์ ์ ์์ฑ์ ์ํด ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณต ์คํ
- ํ์ฅ ํน์ฑ์ ์ดํดํ๊ธฐ ์ํด ๋ค์ํ ๋ฌธ์ ํฌ๊ธฐ ํ ์คํธ
- ์ต์ ํ ์ํฐํฉํธ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด
keep()์ ์ผ๊ด๋๊ฒ ์ฌ์ฉ - ๋์ผ ์กฐ๊ฑด์์ ๋น๊ต (๊ฐ์ ๋ฌธ์ ํฌ๊ธฐ, ๊ฐ์ ํ๋์จ์ด)
์ฑ๋ฅ ์์ฌ๊ฒฐ์ ํ๋ ์์ํฌ:
- ๋จ์ํ๊ฒ ์์: ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ด๋ ์ฐ์ฐ์๋ ์์๋ณ ํจํด๋ถํฐ
- ์ถ์ธกํ์ง ๋ง๊ณ ์ธก์ : ์ด๋ก ์ ๋ถ์์ ๋ฐฉํฅ์, ์ค์ฆ์ ๋ฐ์ดํฐ๊ฐ ๊ฒฐ์ ์
- ๊ท๋ชจ๊ฐ ์ค์: ์๊ท๋ชจ ๋ฌธ์ ์ ์ฑ๋ฅ์ด ๋๊ท๋ชจ ๋ฌธ์ ์ ๋์์ ์์ธกํ์ง ๋ชปํจ
- ์ด๋น์ฉ ์ต์ ํ: ๊ฐ๋ฐ ์๊ฐ vs ๋ฐํ์ ์ฑ๋ฅ์ ๊ท ํ
๋ค์ ๋จ๊ณ
๋ฒค์น๋งํน ๊ธฐ์ ์ ๊ฐ์ถ์๋ค๋ฉด:
- ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ํ๋กํ์ผ๋ง: ์ด ํจํด๋ค์ ์ค์ ์ํฌ๋ก๋์ ์ ์ฉ
- ๊ณ ๊ธ GPU ํจํด: ๋ฆฌ๋์ , ํฉ์ฑ๊ณฑ, ํ๋ ฌ ์ฐ์ฐ ํ๊ตฌ
- ๋ฉํฐ GPU ํ์ฅ: ๋ถ์ฐ GPU ์ปดํจํ ํจํด ์ดํด
- ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ๊ณ ๊ธ ์บ์ฑ์ ๋ ๊น์ด ํ๊ตฌ
๐ก ํต์ฌ ์์ฝ: ๋ฒค์น๋งํน์ ์ด๋ก ์ ์ดํด๋ฅผ ์ค์ง์ ์ธ ์ฑ๋ฅ ์ต์ ํ๋ก ์ ํํฉ๋๋ค. ์ค์ฆ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ํ๋์จ์ด์ ์ํฌ๋ก๋ ํน์ฑ์ ๊ฐ์ฅ ์ ํฉํ ํจํด์ ์ ํํ์ธ์.
์์ผ๋ก์ ๋ฐฉํฅ: ๋ ๋ง์ ์ ์ด๊ฐ ํ์ํ ๋
Part VI์ ํจ์ํ ํจํด์ ๋๋ถ๋ถ์ ์ํฌ๋ก๋์์ ์ฐ์ํ ์ฑ๋ฅ์ ์ ๊ณตํ์ง๋ง, ์ผ๋ถ ์๊ณ ๋ฆฌ์ฆ์ ์ง์ ์ ์ธ ์ค๋ ๋ ๊ฐ ํต์ ์ด ํ์ํฉ๋๋ค:
์ํ ํ๋ก๊ทธ๋๋ฐ์ด ์ ์ฉํ ์๊ณ ๋ฆฌ์ฆ:
- ๋ฆฌ๋์ : ์ค๋ ๋ ๊ทธ๋ฃน์ ๊ฑธ์น ํฉ๊ณ, ์ต๋๊ฐ, ์ต์๊ฐ ์ฐ์ฐ
- ๋์ ์ฐ์ฐ: ๋์ ํฉ, ์ด๋ ์ต๋๊ฐ
- ๋ฐ์ดํฐ ์ ํ: ์ค๋ ๋ ๊ฐ ๋ฐ์ดํฐ ์ฌ๋ฐฐ์น
- ํ๋ ฅ ์๊ณ ๋ฆฌ์ฆ: ์ค๋ ๋ ๊ฐ ๊ธด๋ฐํ ์กฐ์ ์ด ํ์ํ ๊ฒฝ์ฐ
์ฑ๋ฅ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:
Part VII์์๋ Part III์ ์ฌ๋ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋ค์ ์ดํด๋ณด๋ฉฐ ์ํ ์ฐ์ฐ์ด ์ด๋ป๊ฒ:
- ์ฝ๋๋ฅผ ๊ฐ์ํํ๋์ง: ๋ณต์กํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ํจํด์ ๋จ์ผ ํจ์ ํธ์ถ๋ก ๋์ฒด
- ์ฑ๋ฅ์ ํฅ์์ํค๋์ง: ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ ๊ฑฐํ๊ณ ๋ฉ๋ชจ๋ฆฌ ํธ๋ํฝ์ ๊ฐ์
- ์๋ก์ด ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ๋ฅํ๊ฒ ํ๋์ง: ์์ ํจ์ํ ์ ๊ทผ์ผ๋ก๋ ๋ถ๊ฐ๋ฅํ ํจํด์ ๊ตฌํ
๋ค์ ๋ด์ฉ: Part VII: ์ํ ๋ ๋ฒจ ํ๋ก๊ทธ๋๋ฐ - Puzzle 14์ ๋์ ํฉ์ ์์ ํ ์๋กญ๊ฒ ๊ตฌํํ๋ ๊ฒ๋ถํฐ ์์ํฉ๋๋ค.