
๋ค์ด๊ฐ๋ฉฐ
์ปดํจํฐ๋ ์ฌ์ ํ ์ฌ๋์ด ์ดํดํ๊ธฐ์ ๋ณต์กํฉ๋๋ค. ํ๋์ ํ๋ก๊ทธ๋จ์์๋ ๋ค์ํ ์์ ์ ์งํํ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ ์์ธ์ค๋ ๋น๋ฒํฉ๋๋ค. ์ด๋ฐ ํ๋ก๊ทธ๋จ์ด ์ฌ๋ฌ๊ฐ๊ฐ ์ฌ๋ฌ ๋ ธ๋(์ฝ์ด)์์ ๋์ํ๊ธฐ ๋๋ฌธ์ ์ผ๋ถ ํ๋ก๊ทธ๋จ์ด ์๋ชป๋ ๋ฉ๋ชจ๋ฆฌ ์์ธ์ค๋ฅผ ๋ฐ์์ํค๊ฑฐ๋ ๋๋ฆฐ ์์ธ์ค๋ฅผ ๋ฐ์์ํค๊ธฐ๋ ํฉ๋๋ค. ์ค๋์ CPU ๋ ธ๋์ ๋ฉ๋ชจ๋ฆฌ ๋ฒ์๋ฅผ ์งํฌ ์ ์๋ NUMA(Non-Uniformed Memory Access)์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
NUMA(Non-Uniformed Memory Access)
๊ณผ๊ฑฐ์๋ CPU๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋ ๋ฐฉ์์ด ๋ธ๋ฆฟ์ง๋ฅผ ํตํด์๋ง ์ ๊ทผํ์์ต๋๋ค. CPU ์ฝ์ด ์๊ฐ ์ฌ๋ฌ๊ฐ๋ผ๋ ์ค์ง ํ๋์ ๋ธ๋ฆฟ์ง๋ฅผ ํตํด์๋ง ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ ์ฝ์ด๋ณ ์๋ ์ฐจ์ด๋ ํฌ์ง ์์์ต๋๋ค. ๋น์ ๋ฅผ ์ ๊น ๋ค์ด๋ณด๋ฉด CPU ์ฝ์ด๊ฐ ๋์ ๋ด ์น๊ตฌ๋ค์ด๋ผ๊ณ ํ๊ณ ์บ์ ๋ฉ๋ชจ๋ฆฌ๋ ์ง๊ฐ์ด๋ผ๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค. ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ๋ ATM๊ธฐ๊ธฐ๋ผ๊ณ ํ์ ๋, ์ด๋ค ๋ฌผ๊ฑด์ ์ฌ๋ ค๊ณ ํ์ ๋(์ฐ์ฐ), ์ง๊ฐ์ ๋์ด ์์ผ๋ฉด ์ง๊ฐ์์ ๋์ ๊บผ๋
๋๋ค(์บ์ ํํธ). ๋ง์ฝ ์ง๊ฐ์ ๋์ด ์๋ค๋ฉด ATM๊ธฐ๊ธฐ์์ ๋์ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ์ด ๋ ๋์ ๋ด ์น๊ตฌ๋ค์ด ์๋ก ๊ฐ๊ฐ ๋ค๋ฅธ ์์น์ ์๋๋ผ๋ ATM๊ธฐ๊ธฐ๋ 1๊ฐ์ด๊ณ ATM๊ธฐ๊ธฐ๋ก ๊ฑด๋๊ฐ ์ ์๋ ๋ค๋ฆฌ๋ 1๊ฐ๋ผ๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ UMA(Uniformed Memory Access)๋ผ๊ณ ํฉ๋๋ค.

ํ๋ก์ธ์๊ฐ ๋ฐ์ ํ๋ฉด์ ๋ธ๋ฆฟ์ง๊ฐ ํ๋ก์ธ์ ๋ด๋ก ํตํฉ๋๊ณ CPU ๋
ธ๋๋ค์ ๋ฉ๋ชจ๋ฆฌ์ ์์ญ์ ์ชผ๊ฐ์ ๊ฐ์ ธ๊ฐ๊ธฐ ์์ํฉ๋๋ค. ๊ฐ๋จํ ์๋ฅผ ๋ค์ด ์์คํ
์ CPU ์์ผ์ด ๋ค ๊ฐ ์๊ณ , 512GB์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ค์น๋์ด ์๋ค๋ฉด ๋ฌผ๋ฆฌ ์ฃผ์ 0~128G-1๋ฒ์ง๊น์ง์ ๋ฉ๋ชจ๋ฆฌ๋ 0๋ฒ ์์ผ์, 128G~256G-1๋ฒ์ง๊น์ง์ ๋ฉ๋ชจ๋ฆฌ๋ 1๋ฒ ์์ผ์ ์ง์ญ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋๋ ๋ฐฉ์์
๋๋ค.์ด๋ฌํ ๊ตฌ์ฑ์ NUMA๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. ๊ฐ ์์ผ์์ ์๊ธฐ ์์ ๊ณผ ์ฐ๊ฒฐ๋ ๋ก์ปฌ ๋ฉ๋ชจ๋ฆฌ๋ ์ง์ ์ ๊ทผํ๋ฉด ๋๋ฏ๋ก ๋น ๋ฅด์ง๋ง ๋ฆฌ๋ชจํธ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ ๋๋ฆฐ ์ ๊ทผ ์๋ (๋ ์ดํด์)๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ํ๋์ CPU ์์ผ์ ์ฝ์ด ์ฌ๋ฌ ๊ฐ๊ฐ ๋ค์ด๊ฐ ์์ ์ ์๊ธฐ์ ๊ฐ์ ์ง์ญ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ CPU ์ฝ์ด๋ค์ ๋ฌถ์ด์ ํ๋์ NUMA ๋
ธ๋๋ก ์นฉ๋๋ค. 8์ฝ์ด 4์์ผ CPU๋ผ๋ฉด (ํ์ดํผ์ค๋ ๋ฉ์ ๊ฐ์ ํ์ง ์์ ๋์) 0~7๋ฒ ์ฝ์ด๋ NUMA ๋
ธ๋ 0๋ฒ, 8~15๋ฒ ์ฝ์ด๋ NUMA ๋
ธ๋ 1๋ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์
๋๋ค.
NUMA Locality
NUMA locality๋ “์ค๋ ๋๊ฐ ์คํ ์ค์ธ CPU ๋ ธ๋์, ํด๋น ์ค๋ ๋๊ฐ ์ ๊ทผํ๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฐ๋ฅํ ๊ฐ์ NUMA ๋ ธ๋์ ์ํด ์๊ฒ ํ๋ ๊ฒ”์ ์๋ฏธํ๋ฉฐ, ์ด๋ ๊ฒ ํ๋ฉด latency๋ฅผ ์ค์ด๊ณ ๋์ญํญ ํ์ฉ์ ๊ทน๋ํํ ์ ์์ต๋๋ค. ๊ฐ ํ๋ก์ธ์๊ฐ ๋ ๋ฆฝ์ ์ธ ์ง์ญ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์๋ง ์ ๊ทผํ๋ ๊ฒ์ด NUMA ์ง์ญ์ฑ์ ๊ฐํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ฐ๋๋ก ๋ค๋ฅธ ํ๋ก์ธ์์ ๋ฉ๋ชจ๋ฆฌ(์๊ฒฉ ๋ฉ๋ชจ๋ฆฌ)์ ์ ๊ทผํ๊ฒ ๋๋ ๊ฒฝ์ฐ์๋ ๋งํฌ๋ฅผ ํตํ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ์๊ฐ์ด ์์๋์ด ์ฑ๋ฅ ์ ํ๊ฐ ์ผ์ด๋๊ฒ ๋ฉ๋๋ค.

NUMA๊ฐ ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ
NUMA ๋น์ง์ญ ์ ๊ทผ(remote access)๊ฐ ๋ฏธ์น๋ ์ํฅ์ ์ฌ๋ฌ ์์์ ์ํด ๊ฒฐ์ ๋ฉ๋๋ค.
| ์์ธ | ์ํฅ ๋ฐฉํฅ | ์ค๋ช |
| ์ง์ฐ(latency) | ์ฆ๊ฐ | remote ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์ local๋ณด๋ค ๋ ๊ธด ์ ๊ทผ ์๊ฐ์ด ์์๋จ |
| ๋ฐ์ค ํญ(bandwidth) | ๊ฐ์ | cross-node ๋ฉ๋ชจ๋ฆฌ ๋ฒ์ค๊ฐ ๋ณ๋ชฉ์ด ๋ ์ ์์ |
| ์บ์ ์ผ๊ด์ฑ ๋น์ฉ(cache coherence traffic) | ์ฆ๊ฐ | ์๊ฒฉ ๋ ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์ฐ๋ฉด ์บ์ ๊ฐ ํต์ ์ค๋ฒํค๋ ์ ๋ฐ |
| TLB/ํ์ด์ง ์ํฌ ๋น์ฉ | ์ฆ๊ฐ ๊ฐ๋ฅ | ์๊ฒฉ ํ์ด์ง ํ ์ด๋ธ ํ์ ๋น์ฉ์ด ์ปค์ง ์ ์์ |
| ๋ฉ๋ชจ๋ฆฌ ๋๊ธฐ / ๊ฒฝ์ | ์ฆ๊ฐ | ์ฌ๋ฌ CPU๊ฐ ๊ฐ์ remote ๋ ธ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ ๊ฒฝ์ฐ ๋ณ๋ชฉ ๊ฐ๋ฅ |
ํนํ, ๋๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ(workloads with high memory throughput)์ด๋ ๋ฎ์ ์ง์ฐ(latency sensitivity)์ด ์ค์ํ ์์คํ
์์๋ NUMA locality๋ฅผ ์ ๋๋ก ๋ง์ถ์ง ์์ผ๋ฉด 10% ์ด์ ๋๋ ๊ทธ ์ด์์ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
Linux ์ปค๋ ๋ฌธ์์์๋ “memory type์ด๋ ๋ฒ์ค ํน์ฑ์ ๋ฐ๋ผ bandwidth/latency๊ฐ ๋ค๋ฆ”์ ๋ช
์ํ๊ณ ์์ต๋๋ค.
NUMA locality ๋ณด์ฅ์ ์ํ ์ ๋ต
์ค๋ ๋ ์ & CPU ์ฝ์ด ์
์ฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ๊ฒฝ๊ณํด์ผํ ๊ฒ์ ๋ฌธ๋งฅ ๊ตํ(Context Switching)์ ๋๋ค. ๋ฌธ๋งฅ ๊ตํ์ด ๋ฐ์ํ๋ฉด ์ฝ์ด์ ์บ์๊ฐ ๋ ๋ผ๊ฐ๊ธฐ ๋๋ฌธ์, ์ฌ๊ฐํ ์ฑ๋ฅ ์ ํ๋ฅผ ์ผ์ผํต๋๋ค. ์ค๋ ๋ ์๊ฐ CPU ์ฝ์ด ์๋ณด๋ค ๋ง์ผ๋ฉด ์ค์ผ์ค๋ฌ๊ฐ ์์ฃผ ๋ฌธ๋งฅ ๊ตํ์ ๋ฐ์์ํค๊ธฐ ๋๋ฌธ์, ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋ ๋ ์๋ ํ๋์จ์ด ์ฝ์ด ์๋ณด๋ค ์ ๊ฒ ์ค๊ณํฉ๋๋ค.
์คํ์ค์ธ active thread ์ < ์ฝ์ด ์
CPU affinity
CPU affinity๋ ์ด์์ฒด์ ๊ฐ ํน์ ์ค๋ ๋(๋๋ ํ๋ก์ธ์ค)๋ฅผ ํน์ CPU ์ฝ์ด์ ๊ณ ์ ์์ผ ์คํํ๋๋ก ์ ํํ๋ ๊ธฐ๋ฅ์
๋๋ค. ์ฌ์ค ์ NUMA๋ฅผ ์งํค๊ธฐ ์ํ ํต์ฌ ๊ธฐ๋ฅ์ด ๋ฉ๋๋ค. ์๋ฅผ ๋ค๋ฉด "์ด ์ค๋ ๋๋ CPU 2์์๋ง ๋์๋ผ"๋ผ๊ณ ์ง์ ํ๋ ๊ฒ์
๋๋ค.
์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉํ๋ ์ ๋ต์ ๊ฐ์ ธ์๋ดค์ต๋๋ค(๋ฌผ๋ก ์ ๊ฐ ์ ์ฉํ ๊ฑด ์๋๊ณ ์์น..).
1. numactl ๋ก NUMA ๋
ธ๋ ์ ์ฒด๋ฅผ ์ง์ (memory locality ํ๋ณด)
numactl --cpunodebind=0 --membind=0 ./engine
2. ์ฝ๋ ๋ด์์ ์ค๋ ๋๋ณ core pinning(cache locality ํ๋ณด)
#include <pthread.h>
#include <sched.h>
void pin_to_core(int core_id) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}
// NUMA node 0์์ ๋์๊ฐ๋ core 0~3์ ๊ฐ๊ฐ thread pinning
pin_thread_to_core(0);
pin_thread_to_core(1);
pin_thread_to_core(2);
pin_thread_to_core(3);
// ์ค๋ ๋ ์์ฑ์
std::thread t([] {
pin_thread_to_core(2);
run_strategy();
});
์๋๋ฆฌ์ค ์์
HFT(๊ณ ๋น๋ ํธ๋ ์ด๋ฉ) ์์คํ ์ด๋ผ๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค. ์๋์ ๊ฐ์ด CPU affinity๋ฅผ ๊ตฌ์ฑํด๋ณผ ์ ์์ต๋๋ค.
- Core 0: network recv thread (NIC 0๋ฒ NUMA node)
- Core 1: feeding thread
- Core 2~3: strategy threads
- Core 4: order send thread
- Core 5: logging thread
์ด๋ฐ ์์ผ๋ก thread affinity๋ฅผ ๋ช ํํ ๊ณ ์ ํ๋ฉด cache thrash์ context switching์ด ๊ฑฐ์ ์ฌ๋ผ์ง๋๋ค.
๋ง์น๋ฉฐ
NUMA๋ ํ๋ก์ธ์์ ์ค๊ณ๋ฐฉ์์์ ๋์จ ๋จ์ด์ ๋๋ค. ํ๋์จ์ด์ ๋ฐ์ ํ์ฃ . ๊ฒฐ๊ตญ ๊ณ ์ฑ๋ฅ์ด๋ผ๋ ๊ฒ์ ๋ฒ์ฉ์ฑ์ ๋ฒ๋ฆฌ๊ณ , CPU ์ฐ์ฐ ํจ์จ์ ๊ทน๋ํ์ํค๋ ๊ฒ์ ๋๋ค. ์ ์ค๊ณ๋ ๊ณ ์ฑ๋ฅ ํ๋ก๊ทธ๋จ์ CPU ์ฌ์ฉ์จ์ด ์ผ์ ํ๊ฒ High๋ฅผ ์ ์งํ๋๋ผ๊ตฌ์. ์ ๋ ์์ง ๋ถ์กฑํ์ง๋ง NUMA Performance๋ฅผ ์ดํดํ๊ณ ์ด๋ฅผ ๊ณ ๋ คํ์ฌ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ๋ค๋ฉด ๊ณ ํจ์จ ์๋น์ค๋ฅผ ์์ฑํ ์ ์์ ๊ฒ์ ๋๋ค. ์ฑ๋ฅ์ ์ํ ์ ๋ต(์ฌํ๊น์ง ๋ค๋ค๋ ๋ด์ฉ)์ ์ ๋ฆฌํด๋ณด๋ฉด์ ๋ง๋ฌด๋ฆฌํ๊ฒ ์ต๋๋ค.
| ๋ชฉํ | ์ ๋ต |
| ์บ์ ํจ์จ ๊ทน๋ํ | ํ ์ค๋ ๋๋ฅผ ํ ์ฝ์ด์ ๊ณ ์ (1:1 mapping) |
| NUMA ์ต์ ํ | ์ค๋ ๋๊ฐ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ์ ๊ฐ์ NUMA ๋ ธ๋์ ๋ฐฐ์น |
| Throughput ํฅ์ | CPU ๋ถํ๋ฅผ ๋ถ์ฐํ๋, ์ค๋ ๋ ๊ฐ ๋ฐ์ดํฐ ๊ณต์ ๋ฅผ ์ต์ํ |
| Low Latency | ๊ฐ์ ์ฝ์ด/NUMA ๋ ธ๋ ๋ด์์ lock-free ring buffer ์ฌ์ฉ |
| I/O Thread ์ต์ ํ | ๋คํธ์ํฌ ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ ์ค๋ ๋๋ฅผ NIC๊ฐ ์ฐ๊ฒฐ๋ NUMA ๋ ธ๋์ ๊ณ ์ |
'์ปดํจํฐ ๊ตฌ์กฐ & ์ด์์ฒด์ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [๊ณ ์ฑ๋ฅ] CAS(Compare and Swap)๊ณผ Lock-Free Queue (0) | 2025.10.12 |
|---|---|
| [๊ณ ์ฑ๋ฅ] TLB(Translation Lookaside Buffer)์ TLB miss (0) | 2025.10.09 |
| [๊ณ ์ฑ๋ฅ] Cache Memory์ Cache locality(์บ์ ์ง์ญ์ฑ), False sharing(๊ฑฐ์ง ๊ณต์ ) (0) | 2025.10.08 |
| ํ์ด์ง ๊ต์ฒด ์๊ณ ๋ฆฌ์ฆ๊ณผ ํ๋ ์ ํ ๋น (1) | 2023.11.11 |
| ๊ฐ์๋ฉ๋ชจ๋ฆฌ(Virtual Memory)์ ํ์ด์ง ๊ธฐ๋ฒ(Paging) (1) | 2023.11.07 |
๋๊ธ