CPU 토폴로지 (CPU Topology)
현대 프로세서는 단순한 "코어 수 × 스레드 수" 이상의 복잡한 계층 구조를 가집니다. AMD의 칩렛(Chiplet), Intel의 타일(Tile)/하이브리드, ARM의 DynamIQ 등 각 아키텍처는 고유한 토폴로지를 형성하며, 리눅스 커널은 이를 정확히 인식하고 스케줄링·메모리 배치에 반영해야 최적 성능을 달성할 수 있습니다.
핵심 요약
- Socket → Die → Core → Thread — CPU의 물리적 계층 구조입니다.
- SMT(Hyper-Threading) — 하나의 코어가 두 개 이상의 논리 CPU로 동작합니다.
- CPUID — 프로세서가 자신의 토폴로지 정보를 소프트웨어에 알려주는 명령어입니다.
- sched_domain — 커널 스케줄러가 토폴로지를 인식하여 부하를 분산하는 계층 구조입니다.
- lscpu / sysfs —
lscpu명령어와/sys/devices/system/cpu/로 토폴로지를 확인합니다.
단계별 이해
- 토폴로지 확인 —
lscpu를 실행하여 소켓 수, 코어 수, 스레드 수를 확인합니다./sys/devices/system/cpu/cpu0/topology/에서 상세 정보를 볼 수 있습니다. - 계층 이해 — 같은 코어의 SMT 스레드는 L1 캐시를, 같은 다이의 코어는 L3 캐시를 공유합니다.
이 공유 관계가 스케줄링과 성능에 직접적인 영향을 줍니다.
- 스케줄링 도메인 — 커널은 토폴로지를 기반으로 SMT → Core → LLC → NUMA 순의 스케줄링 도메인을 구성합니다.
부하 균형 시 가까운 도메인부터 먼 도메인 순으로 태스크를 이동합니다.
- 성능 최적화 —
taskset이나 cgroup의 cpuset으로 프로세스를 특정 코어에 바인딩할 수 있습니다.캐시 공유 관계를 고려한 바인딩이 성능 최적화의 핵심입니다.
1. AMD Chiplet 아키텍처
AMD는 Zen 아키텍처부터 칩렛(Chiplet) 설계를 도입하여, 하나의 패키지에 여러 개의 소형 다이를 조합하는 방식으로 프로세서를 구성합니다. 이 접근법은 제조 수율 향상, 유연한 코어 수 확장, 비용 효율성이라는 장점을 제공합니다.
CCX (Core CompleX)
CCX는 AMD 프로세서의 기본 컴퓨팅 단위로, 일정 수의 코어가 L3 캐시를 공유하는 클러스터입니다.
| 세대 | CCX 구성 | L3 캐시/CCX | 비고 |
|---|---|---|---|
| Zen1 / Zen+ | 4코어/CCX | 8MB | 2 CCX = 1 CCD |
| Zen2 | 4코어/CCX | 16MB | 2 CCX = 1 CCD, L3 2배 증가 |
| Zen3 | 8코어/CCX | 32MB | 1 CCX = 1 CCD, 통합 L3 |
| Zen4 | 8코어/CCX | 32MB | 5nm, AVX-512 |
| Zen5 | 8코어/CCX | 32MB | 프론트엔드 2-wide 디코드 |
CCX 내부의 코어들은 L3 캐시를 공유하므로 inter-core 지연이 매우 낮습니다. 커널의 스케줄링 도메인에서 MC(Multi-Core) 레벨에 해당합니다.
CCD (Core Chiplet Die)
CCD는 코어가 집적된 물리적 다이(die)입니다.
- Zen1/Zen2: 1 CCD = 2 CCX. 같은 CCD 내 두 CCX 간 통신은 Infinity Fabric을 통하지만, IOD를 경유하지 않아 비교적 빠릅니다.
- Zen3 이후: 1 CCD = 1 CCX. CCX-CCD 구분이 사라지고, 8코어 전체가 32MB L3를 공유합니다.
/* Zen2 CCD 내부 구조 */
┌─────────────────────────────────────┐
│ CCD (Die) │
│ ┌──────────┐ ┌──────────┐ │
│ │ CCX 0 │ │ CCX 1 │ │
│ │ Core0..3 │ │ Core4..7 │ │
│ │ L3 16MB │ │ L3 16MB │ │
│ └────┬─────┘ └────┬─────┘ │
│ └──── IF link ───┘ │
└──────────────┬──────────────────────┘
│ Infinity Fabric → IOD
/* Zen3+ CCD 내부 구조 (통합) */
┌─────────────────────────────────────┐
│ CCD = CCX (Die) │
│ Core0 Core1 Core2 Core3 │
│ Core4 Core5 Core6 Core7 │
│ L3 32MB (공유) │
└──────────────┬──────────────────────┘
│ Infinity Fabric → IOD
IOD (I/O Die)
IOD는 I/O 기능을 전담하는 별도의 다이입니다. Zen2부터 컴퓨팅 다이(CCD)와 I/O 다이(IOD)를 물리적으로 분리하여, 각각 최적의 공정을 적용합니다.
IOD가 담당하는 주요 기능:
- 메모리 컨트롤러(UMC): DDR4/DDR5 채널 관리. EPYC 9004 기준 12채널
- PCIe 컨트롤러: PCIe Gen4/Gen5 레인
- Infinity Fabric 스위치: CCD 간, 소켓 간 통신 라우팅
- xGMI 링크: 멀티소켓 연결 (socket-to-socket)
- 보안 프로세서(PSP): AMD Platform Security Processor
/* 커널에서 AMD IOD 토폴로지 확인 (dmesg) */
// [ 0.123456] node 0 deferred pages: init 2097152
// AMD EPYC 9654 (Genoa): 12 UMC channels, 128 PCIe Gen5 lanes
/* arch/x86/kernel/cpu/amd.c - 토폴로지 파싱 */
static void amd_get_topology(struct cpuinfo_x86 *c)
{
int cpu = c->cpu_index;
/* CPUID Fn8000_001E: Node/Core/Thread 토폴로지 */
if (c->extended_cpuid_level >= 0x8000001e) {
u32 eax, ebx, ecx, edx;
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
c->cpu_core_id = eax; /* Compute Unit ID */
c->cpu_die_id = ecx & 0xff; /* Node(CCD) ID */
c->threads_per_core = ((ebx >> 8) & 0xff) + 1;
}
}
Infinity Fabric
Infinity Fabric(IF)는 AMD의 온-다이/온-패키지/인터-소켓 인터커넥트입니다. Scalable Data Fabric(SDF)과 Scalable Control Fabric(SCF)으로 구성됩니다.
| 통신 경로 | 경유 | 대략적 지연 | 대역폭 |
|---|---|---|---|
| intra-CCX (코어 간) | L3 직접 | ~10-15ns | L3 대역폭 |
| inter-CCX, same CCD (Zen1/2) | IF on-die | ~25-40ns | IF 대역폭 |
| inter-CCD (same socket) | IF → IOD → IF | ~50-80ns | IF 대역폭 |
| inter-socket | xGMI | ~120-180ns | xGMI 대역폭 |
NPS (Nodes Per Socket)
AMD EPYC 프로세서는 NPS(Nodes Per Socket) BIOS 설정으로 단일 소켓 내부를 여러 NUMA 노드로 분할합니다.
| 모드 | NUMA 노드/소켓 | CCD→메모리 매핑 | 적합한 워크로드 |
|---|---|---|---|
| NPS1 | 1 | 모든 CCD → 전체 메모리 채널 | 범용, 대용량 메모리 풀 |
| NPS2 | 2 | CCD 절반씩 → 메모리 채널 절반 | VM 2개 분할 |
| NPS4 | 4 | CCD 1/4씩 → 메모리 채널 1/4 | HPC, 지연 최소화 |
# NPS 모드 확인 (NUMA 노드 수로 추정)
$ numactl --hardware
available: 4 nodes (0-3) # NPS4 모드
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 64169 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 64256 MB
...
node distances:
node 0 1 2 3
0: 10 12 12 12
1: 12 10 12 12
2: 12 12 10 12
3: 12 12 12 10
Zen 세대별 진화
| 세대 | 공정 | CCX/CCD | 최대 CCD | L3/CCX | IF 세대 | 메모리 |
|---|---|---|---|---|---|---|
| Zen1 | 14nm | 2 CCX(4c)/CCD | 4 (EPYC 7001) | 8MB | IF 1.0 | DDR4-2666 |
| Zen2 | 7nm CCD / 14nm IOD | 2 CCX(4c)/CCD | 8 (EPYC 7002) | 16MB | IF 2.0 | DDR4-3200 |
| Zen3 | 7nm | 1 CCX(8c)=CCD | 8 (EPYC 7003) | 32MB | IF 3.0 | DDR4-3200 |
| Zen4 | 5nm CCD / 6nm IOD | 1 CCX(8c)=CCD | 12 (EPYC 9004) | 32MB | IF 4.0 | DDR5-4800 |
| Zen5 | 4nm/3nm | 1 CCX(8c)=CCD | 16 (EPYC 9005) | 32MB | IF 5.0 | DDR5-6000 |
EPYC / Ryzen / Threadripper 비교
| 제품군 | 소켓 | 최대 CCD | 최대 코어 | 메모리 채널 | PCIe 레인 | NPS 지원 |
|---|---|---|---|---|---|---|
| EPYC 9004 (Genoa) | SP5 | 12 | 96 | 12×DDR5 | 128 Gen5 | NPS1/2/4 |
| EPYC 9005 (Turin) | SP5 | 16 | 128 | 12×DDR5 | 128 Gen5 | NPS1/2/4 |
| Threadripper 7000 | sTR5 | 8 | 64 | 4×DDR5 | 48 Gen5 | NPS1 |
| Ryzen 9000 (Granite Ridge) | AM5 | 2 | 16 | 2×DDR5 | 28 Gen5 | N/A |
| Ryzen 9000 (Strix Point) | FP8 | 1 (모놀리식) | 12 | LPDDR5X | 내장 | N/A |
2. Intel 아키텍처
2.1 Tile 아키텍처
Intel은 서버 프로세서(Sapphire Rapids, Granite Rapids)에서 EMIB(Embedded Multi-die Interconnect Bridge)를 사용한 타일 기반 설계를 도입했습니다.
- Sapphire Rapids (SPR): 4타일 구성, 각 타일에 코어 + LLC 슬라이스 + UPI + PCIe. 최대 60코어.
- Granite Rapids (GNR): Performance-core(P-core) 전용 3타일 + I/O 타일, 최대 128코어.
- SNC(Sub-NUMA Clustering): 타일 경계를 따라 소켓 내부를 NUMA 노드로 분할. SNC2(2 NUMA) 또는 SNC4(4 NUMA) 모드로 지연 최소화.
클라이언트 프로세서에서도 Meteor Lake부터 분리형 타일 설계(Foveros 3D 패키징)가 도입되어, Compute/SoC/GFX/IOE 타일로 구성됩니다(자세한 내용은 2.12 분리형 SoC 설계 참조).
# SNC 모드 확인 (Sapphire Rapids, SNC4)
$ lscpu | grep -i numa
NUMA node(s): 4
NUMA node0 CPU(s): 0-14,60-74
NUMA node1 CPU(s): 15-29,75-89
NUMA node2 CPU(s): 30-44,90-104
NUMA node3 CPU(s): 45-59,105-119
2.2 P-core / E-core 하이브리드
Alder Lake(12세대)부터 클라이언트 프로세서에 하이브리드 아키텍처를 도입했습니다. 이는 단일 다이(또는 패키지)에 고성능 P-core(Performance)와 고효율 E-core(Efficient)를 혼합 배치하는 설계입니다.
하이브리드 도입 배경:
- 전력 효율: 무어의 법칙 둔화로 단순히 코어를 늘리는 것만으로는 성능/와트 개선이 한계에 도달. 경량 워크로드를 소형 코어로 처리하면 전체 패키지 전력을 대폭 절감
- 열 제약: 데스크탑 65~125W, 랩탑 15~45W TDP 내에서 코어 수 확장. E-core는 P-core 대비 1/4~1/5 면적으로 동일 다이에 더 많은 코어 집적 가능
- 멀티태스킹 최적화: 포그라운드(게임, 컴파일)는 P-core, 백그라운드(인덱싱, 업데이트)는 E-core에서 처리하여 체감 성능 향상
| 특성 | P-core (Performance) | E-core (Efficient) |
|---|---|---|
| 마이크로아키텍처 | Golden Cove / Raptor Cove / Lion Cove | Gracemont / Crestmont / Skymont |
| SMT | 지원 (2 스레드/코어) | 미지원 (1 스레드/코어) |
| L2 캐시 | 1.25~3MB/코어 (개별) | 2~4MB/4코어 클러스터 (공유) |
| ISA 차이 | AVX-512 (세대별 상이) | AVX-512 미지원 |
| IPC | 높음 | P-core 대비 ~70-85% (세대별 향상) |
| 전력 효율 | 성능 우선 | 와트당 성능 우수 |
| 다이 면적 | 크다 (~4mm² @Intel 7) | 작다 (~1mm² @Intel 7) |
E-core 클러스터 토폴로지: E-core 4개가 하나의 클러스터(Cluster)를 이루며, 클러스터 내 L2 캐시를 공유합니다. 커널에서는 이 클러스터를 CL(Cluster) 스케줄링 도메인 레벨로 인식합니다. 같은 클러스터 내 E-core 간 데이터 교환은 L2를 통해 이루어지므로 지연이 매우 낮지만, 다른 클러스터의 E-core나 P-core와의 통신은 링 버스/LLC를 경유합니다.
2.3 P-core 마이크로아키텍처
P-core는 Intel의 고성능 마이크로아키텍처 계열로, 넓은 프론트엔드와 깊은 OoO(Out-of-Order) 파이프라인을 특징으로 합니다.
| 마이크로아키텍처 | 세대 | 디코드 폭 | ROB 크기 | 실행 포트 | L2/코어 | 주요 특징 |
|---|---|---|---|---|---|---|
| Golden Cove | Alder Lake (12th) | 6-wide | 512 | 12 | 1.25MB | 최초 하이브리드 P-core, 10-wide alloc |
| Raptor Cove | Raptor Lake (13th) | 6-wide | 512 | 12 | 2MB | L2 확대, 클럭 개선 (최대 6.0GHz) |
| Redwood Cove | Meteor Lake (Core Ultra 1) | 6-wide | 512 | 12 | 2MB | 전력 게이팅 향상, Compute tile 분리 |
| Lion Cove | Arrow/Lunar Lake (Core Ultra 2) | 8-wide | 576 | 12 | 2.5~3MB | 디코드 폭 확대, AVX-512 복원(P-core 한정) |
Golden Cove (Alder Lake) — P-core의 첫 하이브리드 설계입니다. 6-wide 디코드, 512-entry ROB(Reorder Buffer), 12개 실행 포트를 갖추어 이전 세대(Cypress Cove) 대비 ~19% IPC 향상을 달성했습니다. L2 캐시는 코어당 1.25MB이며, 프리페칭 개선과 브랜치 예측기 확장이 적용되었습니다.
Raptor Cove (Raptor Lake) — Golden Cove의 파이프라인을 유지하면서 L2를 2MB로 확대하고, 클럭 스케일링을 개선하여 최대 부스트 6.0GHz를 달성했습니다. 캐시 프리페칭 개선으로 메모리 집약적 워크로드에서 추가 IPC 향상이 있습니다.
Redwood Cove (Meteor Lake) — 분리형 Compute tile(Intel 4 공정)에 탑재됩니다. 파이프라인은 Golden Cove와 유사하지만, 타일 단위 전력 게이팅으로 유휴 시 P-core 타일 전체를 전력 차단할 수 있어 배터리 수명이 크게 개선됩니다.
Lion Cove (Arrow Lake / Lunar Lake) — 디코드 폭을 8-wide로 확대하고 ROB를 576개로 늘렸습니다. 가장 주목할 변화는 P-core 한정으로 AVX-512를 복원한 것입니다. E-core에서는 여전히 AVX-512를 지원하지 않으므로, 커널은 ISA 비대칭성을 처리해야 합니다(2.9 ISA 호환성 참조).
2.4 E-core 마이크로아키텍처
E-core는 "느린 코어"가 아닌 "효율 코어"입니다. Skylake급 IPC를 달성하면서 훨씬 낮은 전력과 작은 다이 면적으로 동작하도록 설계되었습니다.
| 마이크로아키텍처 | 세대 | 디코드 | 클러스터 구성 | L2/클러스터 | IPC (vs P-core) |
|---|---|---|---|---|---|
| Gracemont | Alder Lake / Raptor Lake | 2-wide × 2 파이프 | 4코어/클러스터 | 2MB (ADL) / 4MB (RPL) | ~70% |
| Crestmont | Meteor Lake / Lunar Lake LP | 향상된 프론트엔드 | 4코어/클러스터 | 4MB | ~80-85% |
| Skymont | Arrow Lake / Lunar Lake | 추가 IPC 개선 | 4코어/클러스터 | 4MB | ~85% |
Gracemont (Alder Lake/Raptor Lake) — 2개의 독립적인 2-wide 디코드 파이프를 사용하는 독특한 클러스터 구조입니다. SMT를 지원하지 않는 대신 코어 자체를 소형화하여, P-core 1개의 다이 면적에 E-core 4개를 집적합니다. 4코어가 하나의 클러스터를 이루어 L2 캐시를 공유하며, 이 공유 구조가 커널에서 CL(Cluster) 스케줄링 도메인을 형성합니다.
Crestmont (Meteor Lake) — 프론트엔드 분기 예측 개선과 백엔드 실행 유닛 확장으로 IPC가 P-core 대비 ~80-85% 수준으로 향상되었습니다. Meteor Lake SoC tile의 LP E-core(2.5절 참조)로도 사용되며, 이 경우 낮은 클럭(1~2GHz)으로 동작합니다.
Skymont (Arrow Lake / Lunar Lake) — 추가적인 IPC 개선으로 Gracemont 대비 최대 ~38% 향상을 달성했습니다. 벡터 처리 능력도 강화되어 256-bit SIMD 처리량이 증가했습니다.
2.5 LP E-core와 3계층 코어
Meteor Lake부터 SoC tile에 LP E-core(Low-Power Efficient core)가 추가되어, 프로세서가 3계층 코어 구조를 갖게 되었습니다.
| 계층 | 코어 타입 | 위치 | 특성 | 용도 |
|---|---|---|---|---|
| 1 (최고성능) | P-core | Compute tile | 높은 클럭, 넓은 파이프라인 | 게임, 컴파일, 싱글스레드 집약 |
| 2 (효율) | E-core | Compute tile | 중간 클럭, 4코어 클러스터 | 멀티스레드, 백그라운드 |
| 3 (초저전력) | LP E-core | SoC tile | 1~2GHz, 2코어 구성 | 경량 작업, 대기 시 유지 |
LP E-core의 특성:
- 위치: SoC tile(TSMC N6 공정)에 위치하여, Compute tile이 전력 차단(power gate)된 상태에서도 독립 동작 가능
- 구성: 2코어, Crestmont 마이크로아키텍처 기반이지만 낮은 클럭(1~2GHz)으로 동작
- 시나리오: 메신저 알림, 음악 재생, 시스템 유지 관리 등 Compute tile을 깨울 필요 없는 경량 작업
- Lunar Lake: LP E-core 2코어(Crestmont)가 SoC tile에 위치, Compute tile에는 P-core 4개 + E-core 4개
커널 영향: 3계층 코어 구조에서 스케줄러는 추가적인 우선순위 레벨을 관리해야 합니다. ITMT(2.8절)에서 LP E-core는 가장 낮은 우선순위를 받으며, 스케줄링 도메인에서도 별도의 Module 레벨로 인식될 수 있습니다.
2.6 세대별 진화
| 세대 | 공정 | P-core | E-core | LP E | P수 | E수 | P-L2 | E-L2/CL | L3 | 메모리 | 설계 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Alder Lake (12th) | Intel 7 | Golden Cove | Gracemont | - | 8 | 8 | 1.25MB | 2MB | 30MB | DDR5-4800 | 모놀리식 |
| Raptor Lake (13th) | Intel 7 | Raptor Cove | Gracemont | - | 8 | 16 | 2MB | 4MB | 36MB | DDR5-5600 | 모놀리식 |
| Meteor Lake (Ultra 1) | Intel 4/N6/N5 | Redwood Cove | Crestmont | Crestmont | 6 | 8 | 2MB | 4MB | 12MB | LPDDR5X | 분리형(Foveros) |
| Arrow Lake (Ultra 2) | TSMC N3/N6 | Lion Cove | Skymont | - | 8 | 16 | 3MB | 4MB | 36MB | DDR5-5600 | 분리형 |
| Lunar Lake (Ultra 2) | TSMC N3/N6 | Lion Cove | Skymont | Crestmont | 4 | 4 | 2.5MB | 4MB | 12MB | LPDDR5X | 분리형 |
2.7 코어 타입 탐지 — CPUID Leaf 0x1A
하이브리드 프로세서에서 커널은 각 논리 CPU가 P-core인지 E-core인지 식별해야 합니다. Intel은 CPUID Leaf 0x1A (Native Model ID Enumeration)를 통해 이 정보를 제공합니다.
| EAX 비트 | 필드 | 값 | 의미 |
|---|---|---|---|
| [31:24] | Core Type | 0x20 | Atom (E-core) |
| [31:24] | Core Type | 0x40 | Core (P-core) |
| [23:0] | Native Model ID | - | 마이크로아키텍처별 고유 ID |
/* arch/x86/kernel/cpu/intel.c — 하이브리드 코어 타입 탐지 */
static void detect_hybrid_cpu(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
if (!cpu_has(c, X86_FEATURE_HYBRID_CPU))
return;
cpuid(0x1a, &eax, &ebx, &ecx, &edx);
/* EAX[31:24] = Core Type
* 0x20 = Intel Atom (E-core)
* 0x40 = Intel Core (P-core) */
c->topo.core_type = (eax >> 24) & 0xff;
c->topo.native_model_id = eax & 0xffffff;
}
/* X86_FEATURE_HYBRID_CPU는 CPUID Leaf 7, ECX bit 15로 탐지
* (CPUID.07H:EDX[15] = Hybrid 지원 여부) */
CPUID 0x1F V2 Extended Topology와의 연동: Leaf 0x1F에서 Module 레벨(level_type=3)을 통해 E-core 클러스터를 식별할 수 있습니다. 같은 Module에 속한 E-core들은 L2를 공유하며, 커널은 이를 CL 스케줄링 도메인으로 매핑합니다.
# 코어 타입 확인 (sysfs)
$ for cpu in /sys/devices/system/cpu/cpu*/topology; do
if [ -f "$cpu/core_type" ]; then
echo "$(basename $(dirname $cpu)): $(cat $cpu/core_type)"
fi
done
cpu0: 64 # 0x40 = P-core (Intel Core)
cpu1: 64
...
cpu16: 32 # 0x20 = E-core (Intel Atom)
cpu17: 32
...
2.8 ITMT 비대칭 스케줄링
ITMT(Intel Turbo Boost Max Technology 3.0)는 코어별 성능 차이를 커널 스케줄러에 반영하는 메커니즘입니다. 하이브리드 프로세서에서 P-core > E-core > LP E-core 우선순위를 설정하여 비대칭 스케줄링을 구현합니다.
/* arch/x86/kernel/itmt.c — ITMT 우선순위 설정 */
/* 코어별 성능 우선순위를 스케줄러에 등록 */
void sched_set_itmt_core_prio(int prio, int cpu)
{
per_cpu(sched_core_priority, cpu) = prio;
}
/* ITMT 활성화 — sched_domain에 SD_ASYM_PACKING 플래그 설정 */
void sched_set_itmt_support(void)
{
sysctl_sched_itmt_enabled = 1;
rebuild_sched_domains();
}
/*
* 동작 원리:
* 1. intel_pstate 또는 HFI 드라이버가 각 코어의 성능 순위를 파악
* 2. sched_set_itmt_core_prio()로 코어별 우선순위 설정
* 예: P-core = 200, E-core = 100, LP E-core = 50
* 3. SD_ASYM_PACKING이 설정된 도메인에서 스케줄러는
* 높은 우선순위 코어를 먼저 채움
* 4. 워크로드가 줄어들면 낮은 우선순위 코어에서 먼저 제거
*/
주요 커널 인터페이스:
/proc/sys/kernel/sched_itmt_enabled: ITMT 활성화/비활성화 (0 또는 1)SD_ASYM_PACKING: 스케줄링 도메인 플래그로, 비대칭 코어 배치 시 우선순위 기반 태스크 이동- HFI 드라이버가
perf_cap값을 ITMT 우선순위로 변환하여, Thread Director의 실시간 판단이 스케줄러에 반영됨
# ITMT 활성 상태 확인
$ cat /proc/sys/kernel/sched_itmt_enabled
1
# 스케줄링 도메인에서 ASYM_PACKING 플래그 확인
$ cat /proc/sys/kernel/sched_domain/cpu0/domain0/flags
... SD_ASYM_PACKING ...
2.9 ISA 호환성
하이브리드 아키텍처의 핵심 과제 중 하나는 P-core와 E-core 간 ISA(Instruction Set Architecture) 차이입니다. 특히 AVX-512가 세대별로 달라지는 점이 커널과 사용자 공간 모두에 영향을 줍니다.
| 세대 | P-core AVX-512 | E-core AVX-512 | OS에 노출 |
|---|---|---|---|
| Alder Lake (12th) | 하드웨어 존재 | 미지원 | E-core 비활성 시 일부 SKU에서 사용 가능 (BIOS) |
| Raptor Lake (13th) | 퓨즈 차단 | 미지원 | 완전 비활성 |
| Meteor Lake | 미지원 | 미지원 | 비활성 |
| Arrow Lake / Lunar Lake | 복원 (지원) | 미지원 | P-core에서만 사용 가능 |
커널의 ISA 처리 원칙 — 최소 공통 분모:
기본적으로 커널은 모든 코어가 지원하는 ISA의 교집합만 사용자 공간에 노출합니다. E-core가 AVX-512를 지원하지 않으면, CPUID를 통해 OS에 AVX-512가 광고되지 않습니다. 따라서 Alder Lake~Meteor Lake에서는 AVX-512를 사용할 수 없습니다.
Arrow Lake+에서의 변화: Lion Cove P-core에서 AVX-512가 복원되었지만, Skymont E-core는 여전히 미지원입니다. Intel은 이 비대칭 ISA를 처리하기 위해:
- AVX-512 명령어가 E-core에서 실행되면
#UD(Undefined Instruction) 예외 발생 - 커널은 AVX-512를 사용하는 스레드를 P-core에 고정(pin)하거나, 사용자 공간에서
sched_setaffinity()로 P-core만 지정해야 함 - CPUID Leaf 0x1A의 코어 타입 정보와 연동하여 ISA 능력을 코어별로 구분
taskset이나 sched_setaffinity()로 P-core에 명시적으로 고정하지 않으면, 스케줄러가 E-core로 마이그레이션할 때 SIGILL이 발생할 수 있습니다. 커널 6.x에서 이를 자동 처리하는 패치가 진행 중이지만, 현재는 사용자 공간에서 주의가 필요합니다.
2.10 Intel Thread Director
Intel Thread Director(ITD)는 하드웨어 기반의 스레드 분류기로, 각 스레드의 명령어 mix를 실시간 분석하여 P-core/E-core 배치를 최적화합니다.
IPC 클래스 분류: Thread Director는 스레드가 실행하는 명령어 패턴을 모니터링하여 4개 IPC 클래스 중 하나를 할당합니다:
| IPC 클래스 | 명령어 특성 | 권장 코어 | 예시 |
|---|---|---|---|
| Class 0 | 범용 코드 | P-core 또는 E-core | 일반 애플리케이션 |
| Class 1 | 정수 연산 중심 | E-core 충분 | 웹 브라우징, 스크립트 |
| Class 2 | 벡터/SIMD 연산 | P-core 선호 | 미디어 인코딩 |
| Class 3 | FP/AVX 집중 | P-core 강력 선호 | 과학 계산, 게임 물리 |
/* HFI (Hardware Feedback Interface) 테이블 구조 */
struct hfi_cpu_data {
u8 perf_cap; /* 성능 능력: 0(최저)~255(최고) */
u8 ee_cap; /* 에너지 효율: 0(최저)~255(최고) */
};
/*
* 커널 드라이버: drivers/thermal/intel/intel_hfi.c
*
* HFI 테이블은 MMIO 영역에 매핑되며, 인터럽트로 갱신 알림.
* 갱신 주기: 약 ~100ms (워크로드 변화 시 동적 조절)
*
* 열 제한(thermal throttling) 시 perf_cap이 동적으로 감소:
* 정상 → P-core perf_cap=255, E-core perf_cap=128
* 열 제한 → P-core perf_cap=180, E-core perf_cap=100
* 이를 통해 스케줄러가 열 상태에 따라 배치를 자동 조절
*/
static void intel_hfi_process_event(struct work_struct *work)
{
struct hfi_instance *hfi = container_of(work, ...);
/* HFI 테이블에서 각 CPU의 perf_cap/ee_cap 읽기 */
raw_spin_lock_irq(&hfi->table_lock);
memcpy(hfi->local_table, hfi->hw_table, hfi->table_size);
raw_spin_unlock_irq(&hfi->table_lock);
/* ITMT 우선순위 갱신 → 스케줄러에 용량 변경 알림 */
sched_update_cpu_topology();
}
HFI → ITMT → 스케줄러 연동 흐름:
- Thread Director가 IPC 클래스를 계산하여 HFI 테이블에 기록
- HFI 인터럽트 →
intel_hfi_process_event()→ HFI 테이블 복사 perf_cap/ee_cap값을 ITMT 우선순위로 변환 →sched_set_itmt_core_prio()sched_update_cpu_topology()→ 스케줄링 도메인 재구축- CFS 스케줄러가
SD_ASYM_PACKING플래그에 따라 높은 우선순위 코어에 태스크 배치
2.11 캐시 토폴로지
Intel의 LLC(Last-Level Cache)는 슬라이스 형태로 분산되어 있으며, 링 버스 또는 메시 인터커넥트로 연결됩니다.
- 링 버스: 클라이언트 및 초기 서버(~Broadwell). 코어마다 LLC 슬라이스가 링에 연결.
- 메시 인터커넥트: Skylake-SP 이후 서버. 2D 메시에 코어·LLC·Home Agent 분산.
- SNC 모드: 메시를 2~4개 영역으로 분할하여, 각 영역이 로컬 메모리 컨트롤러와 매핑. NUMA 노드로 노출.
2.12 분리형 SoC 설계 — Meteor Lake+
Meteor Lake부터 Intel은 Foveros 3D 패키징을 사용하여 여러 타일을 하나의 패키지에 조합하는 분리형(disaggregated) 설계를 클라이언트 프로세서에 도입했습니다.
4-Tile 구조 (Meteor Lake):
- Compute tile (Intel 4): P-core(Redwood Cove) + E-core(Crestmont) + L3 캐시
- SoC tile (TSMC N6): LP E-core(Crestmont 2코어) + NPU(AI 엔진) + 미디어 엔진 + 디스플레이 엔진
- GFX tile (TSMC N5): Xe-LPG GPU (128 EU)
- IOE tile (TSMC N6): PCIe Gen5, Thunderbolt 4, USB 4, 기타 I/O
각 타일은 독립적인 FIVR(Fully Integrated Voltage Regulator)를 탑재하여 전압/주파수를 개별 제어합니다. Compute tile이 유휴 상태이면 전력을 완전히 차단하고, SoC tile의 LP E-core만으로 경량 작업을 처리할 수 있습니다.
Lunar Lake 변형: GPU를 SoC tile에 통합하고, 메모리(LPDDR5X)를 패키지 위에 직접 적층(Package-on-Package)하여 더 작은 폼팩터를 달성했습니다.
커널 토폴로지 영향:
- CPUID 0x1F에서
Tile레벨(level_type=4)이 보고되어, 커널이 크로스 타일 코어 간 높은 지연을 인식 - Compute tile과 SoC tile의 코어 간 통신은 Foveros 인터커넥트를 경유하므로, 같은 tile 내 코어 간 통신보다 지연이 높음
- 캐시 코히런시: L3는 Compute tile에만 존재하며, LP E-core(SoC tile)는 L3 없이 동작
3. ARM 아키텍처
big.LITTLE / DynamIQ
ARM은 이기종 멀티프로세싱(HMP)의 선구자입니다.
| 기술 | 세대 | 특징 |
|---|---|---|
| big.LITTLE | 2011~ | big/LITTLE 코어가 별도 클러스터, 클러스터 단위 전환 또는 HMP |
| DynamIQ | 2017~ | 단일 클러스터 내 이종 코어 혼합 가능, DSU 기반 L3 공유 |
DynamIQ에서는 하나의 클러스터에 Cortex-X4 + Cortex-A720 + Cortex-A520 같은 3종 코어를 혼합할 수 있습니다.
DSU (DynamIQ Shared Unit)
DSU는 DynamIQ 클러스터의 핵심 IP로, L3 캐시 관리와 클러스터 내 코히런시를 담당합니다.
- DSU-AE (Automotive Enhanced): 자율주행 등 안전 등급 요구사항 충족
- DSU-110: 최대 8코어, L3 최대 16MB
- DSU-120: 최대 12코어, L3 최대 32MB, 3종 코어 지원
- Snoop Filter를 내장하여 코히런시 트래픽 최적화
CMN (Coherent Mesh Network)
ARM 서버 SoC(Neoverse)에서는 CMN(Coherent Mesh Network)으로 다수의 클러스터를 연결합니다.
| 노드 유형 | 역할 |
|---|---|
| XP (Crosspoint) | 메시 라우터, 패킷 라우팅 |
| RN-F (Request Node - Full) | 코어 클러스터 연결점, 풀 코히런시 |
| HN-F (Home Node - Full) | SLC(System-Level Cache) 슬라이스, 디렉토리 기반 코히런시 |
| SN-F (Slave Node - Full) | 메모리 컨트롤러, PCIe 인터페이스 |
| MN (Miscellaneous Node) | DVM(Distributed Virtual Memory) 브로드캐스트 |
/* ARM CMN PMU 드라이버: drivers/perf/arm-cmn.c
* CMN 메시 토폴로지를 런타임에 탐지 */
static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
{
void __iomem *reg;
u64 val;
/* Configuration 영역에서 메시 크기, 노드 수 읽기 */
val = readq_relaxed(cmn->base + CMN_CFGM_INFO_GLOBAL);
cmn->mesh_x = FIELD_GET(CMN_INFO_MESH_X, val);
cmn->mesh_y = FIELD_GET(CMN_INFO_MESH_Y, val);
...
}
Cortex-X/A 시리즈
| 코어 | 등급 | 특징 | 대표 SoC |
|---|---|---|---|
| Cortex-X4/X925 | 초고성능 | 넓은 OoO, 대형 L2 | Snapdragon 8 Gen 3, Dimensity 9300 |
| Cortex-A720/A725 | 고성능 | A78 후속, 균형 잡힌 IPC | 대부분의 플래그십 SoC |
| Cortex-A520 | 효율 | A510 후속, 인오더→아웃오브오더 전환 | 모든 최신 모바일 SoC |
| Neoverse V2/V3 | 서버 | SVE2, 넓은 파이프라인, 대형 캐시 | Graviton 4, Ampere |
| Neoverse N2/N3 | 서버(효율) | 코어 수 확장 최적화 | Graviton 3, Cobalt 100 |
4. 아키텍처 간 비교
토폴로지 구조 비교
| 항목 | AMD (Zen4/5) | Intel (SPR/RPL) | ARM (Neoverse/DynamIQ) |
|---|---|---|---|
| 기본 단위 | CCX (8코어+L3) | 코어 (P/E 구분) | 클러스터 (DSU) |
| 중간 단위 | CCD (물리 다이) | Tile / E-core 클러스터 | CMN 메시 노드 |
| 인터커넥트 | Infinity Fabric (IOD 경유) | Ring Bus / Mesh | CMN 메시 / NoC |
| 이종 코어 | 없음 (동종) | P-core + E-core | X + A(big) + A(LITTLE) |
| NUMA 분할 | NPS1/2/4 | SNC2/4 | ACPI PPTT |
| 소켓 간 | xGMI (IF) | UPI | CCIX / CXL / 커스텀 |
| 칩렛/타일 | CCD + IOD 분리 | EMIB 타일 | 모놀리식 (서버 일부 칩렛) |
캐시 계층 · 코히런시 프로토콜
| 항목 | AMD | Intel | ARM |
|---|---|---|---|
| L1D/L1I | 32K/32K (Zen4: 48K/32K) | 48K/32K (P), 32K/64K (E) | 코어별 상이 |
| L2 | 1MB/코어 | 1.25-2MB/P, 2-4MB/4E | 256K~2MB/코어 |
| L3/LLC | 32MB/CCD | 슬라이스 분산 (1.875MB/코어) | DSU L3 + SLC(서버) |
| 코히런시 | MOESI | MESIF | MESI / AMBA CHI |
| 디렉토리 | Probe Filter | Snoop Filter | HN-F 디렉토리 |
5. 커널의 토폴로지 탐지
x86 CPUID 기반 탐지
x86 커널은 CPUID 명령어를 사용하여 CPU 토폴로지를 탐지합니다. 핵심 Leaf:
| Leaf | 용도 | 제공 정보 |
|---|---|---|
| 0x0B | Extended Topology | SMT/Core 레벨 ID, 토폴로지 유형 |
| 0x1F | V2 Extended Topology | Module/Tile/Die 레벨 추가 (SPR+) |
| 0x8000001E | AMD 토폴로지 | Compute Unit ID, Node(CCD) ID |
| 0x04 / 0x8000001D | 캐시 토폴로지 | 캐시 레벨별 공유 범위 |
/* arch/x86/kernel/cpu/topology.c - detect_extended_topology() */
int detect_extended_topology(struct cpuinfo_x86 *c)
{
unsigned int eax, ebx, ecx, edx;
unsigned int sub_index = 0;
unsigned int leaf;
/* Leaf 0x1F를 우선 시도 (V2), 없으면 0x0B 사용 */
leaf = 0x1f;
cpuid_count(leaf, 0, &eax, &ebx, &ecx, &edx);
if (ebx == 0) {
leaf = 0x0b;
cpuid_count(leaf, 0, &eax, &ebx, &ecx, &edx);
if (ebx == 0)
return -1;
}
/* ECX[15:8] = 토폴로지 레벨 유형
* 1=SMT, 2=Core, 3=Module, 4=Tile, 5=Die */
do {
cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
unsigned level_type = (ecx >> 8) & 0xff;
unsigned shift = eax & 0x1f;
switch (level_type) {
case 1: /* SMT */
c->x86_max_threads = ebx & 0xffff;
break;
case 2: /* Core */
c->x86_max_cores = ebx & 0xffff;
break;
case 5: /* Die */
c->x86_max_dies = ebx & 0xffff;
break;
}
sub_index++;
} while (level_type != 0);
/* x2APIC ID로 고유 ID 설정 */
c->topo.apicid = edx;
return 0;
}
ARM DT/ACPI 기반 탐지
ARM64 시스템은 Device Tree 또는 ACPI PPTT(Processor Properties Topology Table)로 토폴로지를 기술합니다.
/* Device Tree 예시: cpu-map 노드 */
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu-map {
cluster0 { /* big 클러스터 */
core0 { cpu = <&cpu0>; };
core1 { cpu = <&cpu1>; };
core2 { cpu = <&cpu2>; };
core3 { cpu = <&cpu3>; };
};
cluster1 { /* LITTLE 클러스터 */
core0 { cpu = <&cpu4>; };
core1 { cpu = <&cpu5>; };
core2 { cpu = <&cpu6>; };
core3 { cpu = <&cpu7>; };
};
};
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-x4";
capacity-dmips-mhz = <1024>; /* 상대적 성능 */
};
cpu4: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a520";
capacity-dmips-mhz = <480>; /* big 대비 ~47% */
};
};
/* ACPI PPTT 파싱: drivers/acpi/pptt.c */
static int topology_get_acpi_cpu_tag(struct acpi_table_header *table,
unsigned int cpu,
int level, int flag)
{
struct acpi_pptt_processor *node;
/* PPTT에서 CPU의 프로세서 노드를 탐색
* level 0 = thread, 1 = core, 2 = cluster, 3 = package */
node = acpi_find_processor_node(table, cpu);
while (node && level--) {
node = fetch_pptt_node(table, node->parent);
}
return node ? node->acpi_processor_id : -1;
}
/* arch/arm64/kernel/topology.c - parse_acpi_topology() */
int __init parse_acpi_topology(void)
{
int cpu;
for_each_possible_cpu(cpu) {
int topology_id;
topology_id = find_acpi_cpu_topology(cpu, 0); /* thread */
cpu_topology[cpu].thread_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 1); /* core */
cpu_topology[cpu].core_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 2); /* cluster */
cpu_topology[cpu].cluster_id = topology_id;
topology_id = find_acpi_cpu_topology_package(cpu);
cpu_topology[cpu].package_id = topology_id;
}
return 0;
}
초기화 흐름
커널 부팅 시 토폴로지 구축 순서:
- BSP(Bootstrap Processor)에서
identify_cpu()→ CPUID/PPTT 파싱 - 각 AP(Application Processor) 깨움 →
smp_callin()에서 개별 토폴로지 ID 설정 topology_init()→/sys/devices/system/cpu/cpuN/topology/sysfs 노출sched_init_domains()→ 토폴로지 기반 스케줄링 도메인 구축
start_kernel()
→ setup_arch()
→ early_cpu_init() /* x86: CPUID 기본 파싱 */
→ init_intel_cacheinfo() /* 캐시 토폴로지 */
→ smp_init()
→ cpu_up() (per AP)
→ identify_secondary_cpu()
→ set_cpu_sibling_map() /* SMT 형제 설정 */
→ sched_init_domains() /* 스케줄링 도메인 */
→ topology_init() /* sysfs 노출 */
6. sysfs 토폴로지 인터페이스
cpu topology
커널은 /sys/devices/system/cpu/cpuN/topology/에 각 논리 CPU의 토폴로지 정보를 노출합니다.
| 파일 | 설명 | 예시 (AMD EPYC) |
|---|---|---|
physical_package_id | 물리 소켓 ID | 0 |
die_id | 다이(CCD) ID | 0~11 |
cluster_id | 클러스터 ID (ARM, Intel E-core) | 0 |
core_id | 물리 코어 ID | 0~95 |
thread_siblings | SMT 형제 CPU 비트맵 | 00000003 |
thread_siblings_list | SMT 형제 CPU 목록 | 0,96 |
core_siblings | 같은 패키지 내 CPU 비트맵 | (전체) |
die_cpus_list | 같은 다이의 CPU 목록 | 0-7,96-103 |
# CPU 0의 토폴로지 정보 확인
$ for f in /sys/devices/system/cpu/cpu0/topology/*; do
echo "$(basename $f): $(cat $f)"
done
physical_package_id: 0
die_id: 0
cluster_id: 0
core_id: 0
thread_siblings_list: 0,96
cache hierarchy
# CPU 0의 캐시 계층 확인
$ ls /sys/devices/system/cpu/cpu0/cache/
index0 index1 index2 index3
$ for idx in 0 1 2 3; do
dir=/sys/devices/system/cpu/cpu0/cache/index${idx}
echo "L$(cat $dir/level) $(cat $dir/type): $(cat $dir/size), shared: $(cat $dir/shared_cpu_list)"
done
L1 Data: 32K, shared: 0,96 # SMT 형제 공유
L1 Instruction: 32K, shared: 0,96
L2 Unified: 1024K, shared: 0,96 # 코어 단위
L3 Unified: 32768K, shared: 0-7,96-103 # CCD(CCX) 단위
확인 도구
# lscpu: 가장 간단한 토폴로지 요약
$ lscpu
Architecture: x86_64
CPU(s): 192
Thread(s) per core: 2
Core(s) per socket: 96
Socket(s): 1
NUMA node(s): 4
...
# lstopo (hwloc): 그래픽 토폴로지 뷰
$ lstopo --of ascii
$ lstopo --of png topology.png
# /proc/cpuinfo: 상세 CPU 정보
$ grep -m1 "siblings\|cpu cores\|physical id\|core id" /proc/cpuinfo
# numactl: NUMA 토폴로지 + 메모리
$ numactl --hardware
7. 스케줄링 도메인 계층
SMT → MC → DIE → NUMA
커널 스케줄러는 토폴로지를 기반으로 스케줄링 도메인(sched_domain)의 계층 구조를 구축합니다. 각 레벨은 캐시 공유 범위와 통신 비용을 반영합니다.
| 도메인 레벨 | 의미 | SD 플래그 | 대표 예 |
|---|---|---|---|
| SMT | 하이퍼스레드 형제 | SD_SHARE_CPUCAPACITY | CPU 0 ↔ CPU 96 |
| MC (Multi-Core) | L3 공유 코어 | SD_SHARE_PKG_RESOURCES | CCD 내 8코어 |
| CL (Cluster) | L2 공유 클러스터 | SD_SHARE_CLS_RESOURCES | Intel E-core 4개 |
| DIE | 같은 다이 | — | Intel Tile |
| NUMA | NUMA 노드 | SD_NUMA | NPS 분할 영역 |
NUMA 경계를 넘는 밸런싱의 구체적인 메커니즘 — Automatic NUMA Balancing, 태스크 선호 노드 결정, NUMA 그룹, 메모리 정책(mbind/set_mempolicy) 등은 NUMA 심화 — NUMA-aware 스케줄링에서 상세히 다룹니다.
도메인 구축
/* kernel/sched/topology.c - 스케줄링 도메인 구축 */
/* 기본 토폴로지 레벨 정의 */
static struct sched_domain_topology_level default_topology[] = {
#ifdef CONFIG_SCHED_SMT
{ cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
#endif
#ifdef CONFIG_SCHED_CLUSTER
{ cpu_clustergroup_mask, cpu_cluster_flags, SD_INIT_NAME(CL) },
#endif
#ifdef CONFIG_SCHED_MC
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
#endif
{ cpu_cpu_mask, SD_INIT_NAME(PKG) },
{ NULL, },
};
/* cpu_coregroup_mask: L3를 공유하는 코어 그룹 반환 */
static const struct cpumask *cpu_coregroup_mask(int cpu)
{
return topology_core_cpumask(cpu);
}
/* build_sched_domains: 도메인 트리 구축 */
static int build_sched_domains(const struct cpumask *cpu_map,
struct sched_domain_attr *attr)
{
/* 각 토폴로지 레벨에 대해:
* 1. sched_domain 할당
* 2. sched_group 링 구성
* 3. 로드 밸런싱 파라미터 초기화 */
for_each_sd_topology(tl) {
for_each_cpu(i, cpu_map) {
sd = __build_sched_domain(tl, cpu_map, attr, ...);
...
}
}
...
}
도메인 확인
# 스케줄링 도메인 계층 확인
$ ls /sys/kernel/debug/sched/domains/cpu0/
domain0 domain1 domain2 domain3
# 또는 /proc/sys/kernel/sched_domain/
$ ls /proc/sys/kernel/sched_domain/cpu0/
domain0 domain1 domain2 domain3
# 각 도메인의 이름과 범위
$ cat /proc/sys/kernel/sched_domain/cpu0/domain0/name
SMT
$ cat /proc/sys/kernel/sched_domain/cpu0/domain1/name
MC
$ cat /proc/sys/kernel/sched_domain/cpu0/domain2/name
DIE
$ cat /proc/sys/kernel/sched_domain/cpu0/domain3/name
NUMA
# 밸런싱 간격, 플래그 확인
$ cat /proc/sys/kernel/sched_domain/cpu0/domain1/min_interval
4
$ cat /proc/sys/kernel/sched_domain/cpu0/domain1/flags
559
8. 비대칭 스케줄링
ASYM_PACKING
SD_ASYM_PACKING은 SMT 레벨에서 사용되는 플래그로, 하이퍼스레드 형제 코어에 태스크를 비대칭적으로 배치합니다.
/* kernel/sched/fair.c - SMT 비대칭 패킹 로직 */
/*
* ASYM_PACKING 정책:
* - SMT 형제 중 높은 우선순위(smt_gain이 큰) 스레드를 먼저 채움
* - 두 번째 스레드는 가능하면 다른 물리 코어로 이동
* - 결과: 물리 코어를 최대한 활용하여 IPC 극대화
*
* Intel: 보통 thread 0이 우선순위 높음
* AMD: Preferred Core 기능으로 최적 코어 선별
*/
static int find_busiest_group(struct lb_env *env,
struct sd_lb_stats *sds)
{
if (env->sd->flags & SD_ASYM_PACKING) {
/* 우선순위가 낮은 CPU에서 높은 CPU로 태스크 이동 */
if (sched_asym_prefer(env->dst_cpu, busiest->asym_prefer_cpu))
return busiest;
}
...
}
ASYM_CPUCAPACITY (EAS)
Energy-Aware Scheduling(EAS)은 이종 코어 시스템에서 성능과 에너지 효율의 균형을 맞추는 스케줄러 기능입니다.
/* kernel/sched/fair.c - find_energy_efficient_cpu() */
static int find_energy_efficient_cpu(struct task_struct *p,
int prev_cpu)
{
struct root_domain *rd = cpu_rq(prev_cpu)->rd;
unsigned long best_delta = ULONG_MAX;
int best_cpu = -1;
for_each_cpu_and(cpu, sched_domain_span(sd), p->cpus_ptr) {
unsigned long cur_delta;
/* 각 CPU(performance domain)별 에너지 소비 예측 */
cur_delta = compute_energy(p, cpu, pd);
if (cur_delta < best_delta) {
best_delta = cur_delta;
best_cpu = cpu;
}
}
/* 에너지 절감량이 6% 미만이면 prev_cpu 유지 (마이그레이션 비용) */
if ((prev_delta - best_delta) * 100 < prev_delta * 6)
return prev_cpu;
return best_cpu;
}
/* EAS 활성화 조건:
* 1. SD_ASYM_CPUCAPACITY 플래그 설정
* 2. Energy Model(EM) 등록 (em_dev_register_perf_domain)
* 3. CPU 수가 너무 많지 않을 것 (기본 256 이하) */
Intel Thread Director 커널 통합
/* drivers/thermal/intel/intel_hfi.c - HFI 커널 통합 */
/* HFI 인터럽트 핸들러: 하드웨어가 성능/효율 테이블 갱신 시 호출 */
static void intel_hfi_online(unsigned int cpu)
{
struct hfi_instance *hfi = per_cpu(hfi_instance, cpu);
/* CPU별 성능 능력(perf_cap)과 에너지 효율(ee_cap) 읽기 */
u8 perf_cap = hfi->local_table[cpu].perf_cap;
u8 ee_cap = hfi->local_table[cpu].ee_cap;
/* 스케줄러에 CPU 용량 업데이트 알림
* → CFS의 capacity_of()에 반영
* → 높은 perf_cap = P-core, 높은 ee_cap = E-core 선호 */
topology_set_cpu_capacity(cpu, perf_cap);
}
/* IPC 클래스 기반 코어 선택 (커널 6.6+) */
/* Thread Director가 실시간으로 IPC 클래스를 업데이트하면,
* 스케줄러가 해당 태스크에 적합한 코어 유형을 선택 */
ARM cpu-capacity
ARM에서는 Device Tree의 capacity-dmips-mhz 속성으로 각 코어의 상대적 성능을 지정합니다.
/* drivers/base/arch_topology.c - CPU 용량 설정 */
void topology_normalize_cpu_scale(void)
{
unsigned long capacity, max_capacity = 0;
int cpu;
/* DT의 capacity-dmips-mhz 기반 최대값 탐색 */
for_each_possible_cpu(cpu) {
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
max_capacity = max(max_capacity, capacity);
}
/* 최대 코어 = 1024, 나머지 비례 계산 */
for_each_possible_cpu(cpu) {
capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
capacity = capacity * SCHED_CAPACITY_SCALE / max_capacity;
topology_set_cpu_scale(cpu, capacity);
}
}
/* 결과: big 코어 = 1024, LITTLE = ~480, mid = ~700 등
* → EAS가 이 값을 사용하여 태스크 배치 결정 */
9. 커널 소스 참조
x86 토폴로지
| 파일 | 역할 |
|---|---|
arch/x86/kernel/cpu/topology.c | CPUID 기반 토폴로지 탐지, detect_extended_topology() |
arch/x86/kernel/cpu/amd.c | AMD 전용 토폴로지 (CPUID 0x8000001E) |
arch/x86/kernel/cpu/intel.c | Intel 전용 토폴로지, Thread Director |
arch/x86/kernel/smpboot.c | SMP 부팅, AP 초기화, sibling map |
arch/x86/kernel/cpu/cacheinfo.c | CPUID 기반 캐시 토폴로지 |
ARM64 토폴로지
| 파일 | 역할 |
|---|---|
arch/arm64/kernel/topology.c | ARM64 토폴로지 초기화, PPTT 파싱 |
drivers/base/arch_topology.c | 아키텍처 공통: cpu-capacity, freq-factor |
drivers/acpi/pptt.c | ACPI PPTT 테이블 파서 |
drivers/perf/arm-cmn.c | CMN 메시 PMU 드라이버 |
스케줄러 토폴로지
| 파일 | 역할 |
|---|---|
kernel/sched/topology.c | sched_domain 구축, build_sched_domains() |
kernel/sched/fair.c | CFS 로드 밸런싱, EAS, ASYM_PACKING |
include/linux/topology.h | 토폴로지 매크로/함수 선언 |
drivers/thermal/intel/intel_hfi.c | Intel HFI/Thread Director 드라이버 |
10. 실전 진단 명령 모음
토폴로지 확인
# 전체 토폴로지 요약
$ lscpu -e=CPU,SOCKET,NODE,CORE,L1d:,L1i:,L2:,L3:,ONLINE
# hwloc: 상세 그래픽 토폴로지 (텍스트)
$ lstopo-no-graphics --of ascii
# 특정 CPU의 상세 토폴로지
$ cat /sys/devices/system/cpu/cpu0/topology/die_id
$ cat /sys/devices/system/cpu/cpu0/topology/core_id
$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
# 캐시 공유 관계 확인
$ cat /sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_list
# CPU 용량 확인 (ARM/하이브리드)
$ cat /sys/devices/system/cpu/cpu*/cpu_capacity
sched_domain 확인
# 스케줄링 도메인 이름 확인
$ for d in /proc/sys/kernel/sched_domain/cpu0/domain*/; do
echo "$(basename $d): $(cat ${d}name)"
done
domain0: SMT
domain1: MC
domain2: DIE
domain3: NUMA
# 도메인별 밸런싱 통계 (debugfs)
$ cat /proc/schedstat | head -20
# 태스크의 현재 CPU, 선호도 확인
$ taskset -cp $$
$ cat /proc/$$/status | grep Cpus_allowed
성능 측정
# inter-CCD vs intra-CCD 지연 비교 (perf)
$ perf stat -e cache-misses,cache-references,L1-dcache-load-misses \
taskset -c 0,1 ./benchmark # 같은 CCX 내 코어
$ perf stat -e cache-misses,cache-references,L1-dcache-load-misses \
taskset -c 0,16 ./benchmark # 다른 CCD 코어
# NUMA 지연 측정
$ numactl --hardware
$ numactl --cpunodebind=0 --membind=0 ./benchmark # 로컬
$ numactl --cpunodebind=0 --membind=1 ./benchmark # 리모트
# Intel Thread Director 상태 확인
$ cat /sys/devices/system/cpu/cpu*/topology/ppin 2>/dev/null
$ dmesg | grep -i "hfi\|thread director"
# 스케줄러 디버깅 (ftrace)
$ echo 1 > /sys/kernel/debug/tracing/events/sched/sched_migrate_task/enable
$ cat /sys/kernel/debug/tracing/trace_pipe | head -50