CPU 토폴로지 (CPU Topology)

현대 프로세서는 단순한 "코어 수 × 스레드 수" 이상의 복잡한 계층 구조를 가집니다. AMD의 칩렛(Chiplet), Intel의 타일(Tile)/하이브리드, ARM의 DynamIQ 등 각 아키텍처는 고유한 토폴로지를 형성하며, 리눅스 커널은 이를 정확히 인식하고 스케줄링·메모리 배치에 반영해야 최적 성능을 달성할 수 있습니다.

관련 페이지: NUMA 노드 수준의 메모리 토폴로지는 NUMA 심화 페이지를, CPUID 명령어의 세부 동작은 어셈블리 — CPUID 기반 토폴로지 탐지를, 스케줄러의 전반적인 동작은 프로세스 관리 페이지를 참조하세요.
관련 표준: Intel SDM (CPUID, APIC 토폴로지), AMD APM (토폴로지 열거), ARM DynamIQ (클러스터 구조) — CPU 토폴로지 탐색에 사용되는 프로세서 아키텍처 규격입니다. 종합 목록은 참고자료 — 표준 & 규격 섹션을 참고하세요.
전제 조건: 커널 아키텍처(멀티코어 기초, 특권 레벨)를 먼저 읽으세요.
일상 비유: CPU 토폴로지는 회사 조직도와 같습니다. 소켓은 "지사", 칩렛/다이는 "부서", 코어는 "직원", SMT(하이퍼스레딩) 스레드는 "한 직원이 두 가지 업무를 번갈아 처리"하는 것입니다. 같은 부서 직원끼리는 자료 공유(캐시 공유)가 빠르고, 다른 지사와는 느립니다.

핵심 요약

  • Socket → Die → Core → Thread — CPU의 물리적 계층 구조입니다.
  • SMT(Hyper-Threading) — 하나의 코어가 두 개 이상의 논리 CPU로 동작합니다.
  • CPUID — 프로세서가 자신의 토폴로지 정보를 소프트웨어에 알려주는 명령어입니다.
  • sched_domain — 커널 스케줄러가 토폴로지를 인식하여 부하를 분산하는 계층 구조입니다.
  • lscpu / sysfslscpu 명령어와 /sys/devices/system/cpu/로 토폴로지를 확인합니다.

단계별 이해

  1. 토폴로지 확인lscpu를 실행하여 소켓 수, 코어 수, 스레드 수를 확인합니다.

    /sys/devices/system/cpu/cpu0/topology/에서 상세 정보를 볼 수 있습니다.

  2. 계층 이해 — 같은 코어의 SMT 스레드는 L1 캐시를, 같은 다이의 코어는 L3 캐시를 공유합니다.

    이 공유 관계가 스케줄링과 성능에 직접적인 영향을 줍니다.

  3. 스케줄링 도메인 — 커널은 토폴로지를 기반으로 SMT → Core → LLC → NUMA 순의 스케줄링 도메인을 구성합니다.

    부하 균형 시 가까운 도메인부터 먼 도메인 순으로 태스크를 이동합니다.

  4. 성능 최적화taskset이나 cgroup의 cpuset으로 프로세스를 특정 코어에 바인딩할 수 있습니다.

    캐시 공유 관계를 고려한 바인딩이 성능 최적화의 핵심입니다.

1. AMD Chiplet 아키텍처

AMD는 Zen 아키텍처부터 칩렛(Chiplet) 설계를 도입하여, 하나의 패키지에 여러 개의 소형 다이를 조합하는 방식으로 프로세서를 구성합니다. 이 접근법은 제조 수율 향상, 유연한 코어 수 확장, 비용 효율성이라는 장점을 제공합니다.

CCX (Core CompleX)

CCX는 AMD 프로세서의 기본 컴퓨팅 단위로, 일정 수의 코어가 L3 캐시를 공유하는 클러스터입니다.

세대CCX 구성L3 캐시/CCX비고
Zen1 / Zen+4코어/CCX8MB2 CCX = 1 CCD
Zen24코어/CCX16MB2 CCX = 1 CCD, L3 2배 증가
Zen38코어/CCX32MB1 CCX = 1 CCD, 통합 L3
Zen48코어/CCX32MB5nm, AVX-512
Zen58코어/CCX32MB프론트엔드 2-wide 디코드

CCX 내부의 코어들은 L3 캐시를 공유하므로 inter-core 지연이 매우 낮습니다. 커널의 스케줄링 도메인에서 MC(Multi-Core) 레벨에 해당합니다.

CCD (Core Chiplet Die)

CCD는 코어가 집적된 물리적 다이(die)입니다.

/* 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가 담당하는 주요 기능:

/* 커널에서 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-15nsL3 대역폭
inter-CCX, same CCD (Zen1/2)IF on-die~25-40nsIF 대역폭
inter-CCD (same socket)IF → IOD → IF~50-80nsIF 대역폭
inter-socketxGMI~120-180nsxGMI 대역폭
FCLK / MCLK 관계: Infinity Fabric 클럭(FCLK)과 메모리 클럭(MCLK)은 밀접하게 연결됩니다. Zen2/3에서 FCLK:MCLK = 1:1 동기 모드가 최적이며, 비동기(2:1) 시 IF 지연이 증가합니다. Zen4부터 FCLK 최대치가 높아져 DDR5 고속 메모리와의 동기 범위가 확대되었습니다.

NPS (Nodes Per Socket)

AMD EPYC 프로세서는 NPS(Nodes Per Socket) BIOS 설정으로 단일 소켓 내부를 여러 NUMA 노드로 분할합니다.

모드NUMA 노드/소켓CCD→메모리 매핑적합한 워크로드
NPS11모든 CCD → 전체 메모리 채널범용, 대용량 메모리 풀
NPS22CCD 절반씩 → 메모리 채널 절반VM 2개 분할
NPS44CCD 1/4씩 → 메모리 채널 1/4HPC, 지연 최소화
# 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
NPS와 NUMA 정책: NPS 모드별 NUMA 메모리 정책(mbind, set_mempolicy)과 Automatic NUMA Balancing에 대한 자세한 내용은 NUMA 심화 페이지를 참조하세요.

Zen 세대별 진화

세대공정CCX/CCD최대 CCDL3/CCXIF 세대메모리
Zen114nm2 CCX(4c)/CCD4 (EPYC 7001)8MBIF 1.0DDR4-2666
Zen27nm CCD / 14nm IOD2 CCX(4c)/CCD8 (EPYC 7002)16MBIF 2.0DDR4-3200
Zen37nm1 CCX(8c)=CCD8 (EPYC 7003)32MBIF 3.0DDR4-3200
Zen45nm CCD / 6nm IOD1 CCX(8c)=CCD12 (EPYC 9004)32MBIF 4.0DDR5-4800
Zen54nm/3nm1 CCX(8c)=CCD16 (EPYC 9005)32MBIF 5.0DDR5-6000

EPYC / Ryzen / Threadripper 비교

제품군소켓최대 CCD최대 코어메모리 채널PCIe 레인NPS 지원
EPYC 9004 (Genoa)SP5129612×DDR5128 Gen5NPS1/2/4
EPYC 9005 (Turin)SP51612812×DDR5128 Gen5NPS1/2/4
Threadripper 7000sTR58644×DDR548 Gen5NPS1
Ryzen 9000 (Granite Ridge)AM52162×DDR528 Gen5N/A
Ryzen 9000 (Strix Point)FP81 (모놀리식)12LPDDR5X내장N/A
AMD EPYC 칩렛 아키텍처 (Zen4/Genoa 기준) CCD 0 C0 C1 C2 C3 C4 C5 C6 C7 L3 32MB CCD 1 C0 C1 C2 C3 C4 C5 C6 C7 L3 32MB CCD 2 8C / L3 32MB CCD 3 8C / L3 32MB IF IF IF IF IOD (I/O Die) IF Switch UMC (DDR5) PCIe Gen5 xGMI PSP (보안) CXL 컨트롤러 CCD 4 8C / L3 32MB CCD 5 8C / L3 32MB CCD 6 8C / L3 32MB CCD 7 8C / L3 32MB → Socket 1 DDR5 (12ch)

2. Intel 아키텍처

2.1 Tile 아키텍처

Intel은 서버 프로세서(Sapphire Rapids, Granite Rapids)에서 EMIB(Embedded Multi-die Interconnect Bridge)를 사용한 타일 기반 설계를 도입했습니다.

클라이언트 프로세서에서도 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)를 혼합 배치하는 설계입니다.

하이브리드 도입 배경:

특성P-core (Performance)E-core (Efficient)
마이크로아키텍처Golden Cove / Raptor Cove / Lion CoveGracemont / 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 CoveAlder Lake (12th)6-wide512121.25MB최초 하이브리드 P-core, 10-wide alloc
Raptor CoveRaptor Lake (13th)6-wide512122MBL2 확대, 클럭 개선 (최대 6.0GHz)
Redwood CoveMeteor Lake (Core Ultra 1)6-wide512122MB전력 게이팅 향상, Compute tile 분리
Lion CoveArrow/Lunar Lake (Core Ultra 2)8-wide576122.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)
GracemontAlder Lake / Raptor Lake2-wide × 2 파이프4코어/클러스터2MB (ADL) / 4MB (RPL)~70%
CrestmontMeteor Lake / Lunar Lake LP향상된 프론트엔드4코어/클러스터4MB~80-85%
SkymontArrow 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 처리량이 증가했습니다.

효율 코어의 의미: E-core의 싱글 스레드 성능은 2~3세대 전 P-core(Skylake~Coffee Lake)에 필적합니다. "E-core = 느린 코어"가 아닌 "E-core = 작은 면적에서 충분한 성능"으로 이해해야 합니다. 4개 E-core 클러스터의 멀티스레드 처리량은 2개 P-core 수준이면서, 전력 소비는 절반 이하입니다.

2.5 LP E-core와 3계층 코어

Meteor Lake부터 SoC tile에 LP E-core(Low-Power Efficient core)가 추가되어, 프로세서가 3계층 코어 구조를 갖게 되었습니다.

계층코어 타입위치특성용도
1 (최고성능)P-coreCompute tile높은 클럭, 넓은 파이프라인게임, 컴파일, 싱글스레드 집약
2 (효율)E-coreCompute tile중간 클럭, 4코어 클러스터멀티스레드, 백그라운드
3 (초저전력)LP E-coreSoC tile1~2GHz, 2코어 구성경량 작업, 대기 시 유지

LP E-core의 특성:

커널 영향: 3계층 코어 구조에서 스케줄러는 추가적인 우선순위 레벨을 관리해야 합니다. ITMT(2.8절)에서 LP E-core는 가장 낮은 우선순위를 받으며, 스케줄링 도메인에서도 별도의 Module 레벨로 인식될 수 있습니다.

2.6 세대별 진화

세대공정P-coreE-coreLP EP수E수P-L2E-L2/CLL3메모리설계
Alder Lake (12th)Intel 7Golden CoveGracemont-881.25MB2MB30MBDDR5-4800모놀리식
Raptor Lake (13th)Intel 7Raptor CoveGracemont-8162MB4MB36MBDDR5-5600모놀리식
Meteor Lake (Ultra 1)Intel 4/N6/N5Redwood CoveCrestmontCrestmont682MB4MB12MBLPDDR5X분리형(Foveros)
Arrow Lake (Ultra 2)TSMC N3/N6Lion CoveSkymont-8163MB4MB36MBDDR5-5600분리형
Lunar Lake (Ultra 2)TSMC N3/N6Lion CoveSkymontCrestmont442.5MB4MB12MBLPDDR5X분리형
코어 수 표기: 위 표의 P수/E수는 해당 세대의 최대 구성(K/HX SKU) 기준입니다. 실제 SKU별로 P-core/E-core 수가 다르며, 일부 SKU에서는 E-core가 완전히 비활성화되기도 합니다.

2.7 코어 타입 탐지 — CPUID Leaf 0x1A

하이브리드 프로세서에서 커널은 각 논리 CPU가 P-core인지 E-core인지 식별해야 합니다. Intel은 CPUID Leaf 0x1A (Native Model ID Enumeration)를 통해 이 정보를 제공합니다.

EAX 비트필드의미
[31:24]Core Type0x20Atom (E-core)
[31:24]Core Type0x40Core (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. 워크로드가 줄어들면 낮은 우선순위 코어에서 먼저 제거
 */

주요 커널 인터페이스:

# 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-512E-core AVX-512OS에 노출
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를 처리하기 위해:

ISA 비대칭성 주의: Arrow Lake 이후에서 AVX-512를 사용하려면 해당 스레드가 반드시 P-core에서 실행되어야 합니다. 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 3FP/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 → 스케줄러 연동 흐름:

  1. Thread Director가 IPC 클래스를 계산하여 HFI 테이블에 기록
  2. HFI 인터럽트 → intel_hfi_process_event() → HFI 테이블 복사
  3. perf_cap/ee_cap 값을 ITMT 우선순위로 변환 → sched_set_itmt_core_prio()
  4. sched_update_cpu_topology() → 스케줄링 도메인 재구축
  5. CFS 스케줄러가 SD_ASYM_PACKING 플래그에 따라 높은 우선순위 코어에 태스크 배치

2.11 캐시 토폴로지

Intel의 LLC(Last-Level Cache)는 슬라이스 형태로 분산되어 있으며, 링 버스 또는 메시 인터커넥트로 연결됩니다.

캐시 심화: 캐시 연관도, 교체/쓰기 정책, 코히런시 프로토콜(MESI/MOESI/MESIF), TLB, 프리페칭, Intel RDT, false sharing 등의 자세한 내용은 CPU 캐시 심화 페이지를 참조하세요.

2.12 분리형 SoC 설계 — Meteor Lake+

Meteor Lake부터 Intel은 Foveros 3D 패키징을 사용하여 여러 타일을 하나의 패키지에 조합하는 분리형(disaggregated) 설계를 클라이언트 프로세서에 도입했습니다.

4-Tile 구조 (Meteor Lake):

  1. Compute tile (Intel 4): P-core(Redwood Cove) + E-core(Crestmont) + L3 캐시
  2. SoC tile (TSMC N6): LP E-core(Crestmont 2코어) + NPU(AI 엔진) + 미디어 엔진 + 디스플레이 엔진
  3. GFX tile (TSMC N5): Xe-LPG GPU (128 EU)
  4. 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)하여 더 작은 폼팩터를 달성했습니다.

커널 토폴로지 영향:

Intel Meteor Lake — Foveros 분리형 4-Tile 설계 Compute Tile (Intel 4) P0 2T P1 2T P2 2T P3 2T P4 2T P5 P-core: Redwood Cove, L2 2MB/코어 E-cluster 0 (E0~E3) Crestmont, L2 4MB 공유 E-cluster 1 (E4~E7) Crestmont, L2 4MB 공유 L3 캐시 12MB (Compute tile 전용) FIVR (독립 전압/주파수) SoC Tile (TSMC N6) LP E-core (2코어) Crestmont, 1~2GHz NPU AI 엔진 미디어 디스플레이 IPU 메모리 컨트롤러 (LPDDR5X) FIVR (독립 전압/주파수) Foveros 인터커넥트 (베이스 다이) GFX Tile (TSMC N5) Xe-LPG GPU (128 EU) IOE Tile (TSMC N6) PCIe Gen5 TB4/USB4 기타 I/O 각 타일: 독립 공정 + 독립 FIVR | Compute tile: 전력 차단 가능 | LP E-core: 항시 가동 커널 토폴로지 인식 CPUID 0x1F: Tile 레벨(type=4)로 크로스 타일 지연 인식 LP E-core: CPUID 0x1A core_type=0x20, ITMT 최저 우선순위, Compute tile L3 미공유 Intel 하이브리드 아키텍처 (Alder Lake/Raptor Lake) P-cores (Golden Cove/Raptor Cove) P0 SMT: 2T P1 SMT: 2T P2 SMT: 2T P3 SMT: 2T P4 SMT: 2T P5 SMT: 2T 각 P-core: L2 1.25MB (개별) E-core 클러스터 E-cluster 0 (E0~E3) L2 2MB 공유, 각 1T E-cluster 1 (E4~E7) L2 2MB 공유, 각 1T Ring Bus + LLC (L3 30MB 공유) Intel Thread Director (HFI) Memory Controller (DDR5) PCIe Gen5 / Thunderbolt GPU (내장) P-core: 고성능 워크로드 | E-core: 백그라운드/효율 워크로드 | Thread Director: HW 기반 분류

3. ARM 아키텍처

big.LITTLE / DynamIQ

ARM은 이기종 멀티프로세싱(HMP)의 선구자입니다.

기술세대특징
big.LITTLE2011~big/LITTLE 코어가 별도 클러스터, 클러스터 단위 전환 또는 HMP
DynamIQ2017~단일 클러스터 내 이종 코어 혼합 가능, DSU 기반 L3 공유

DynamIQ에서는 하나의 클러스터에 Cortex-X4 + Cortex-A720 + Cortex-A520 같은 3종 코어를 혼합할 수 있습니다.

DSU (DynamIQ Shared Unit)

DSU는 DynamIQ 클러스터의 핵심 IP로, L3 캐시 관리와 클러스터 내 코히런시를 담당합니다.

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, 대형 L2Snapdragon 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
ARM DynamIQ 클러스터 (모바일 SoC) Cluster 0 (DSU-120) X4L2 2MB A720L2 512K A720L2 512K A720L2 512K L3 12MB (DSU 관리, Snoop Filter) Cluster 1 (DSU-120) A520L2 128K A520L2 128K A520L2 128K A520L2 128K L3 4MB (DSU 관리) CMN / NoC (System Interconnect) DDR5 / LPDDR5X GPU (Mali/Adreno) NPU / DSP PCIe / USB / I/O DynamIQ: 단일 클러스터 내 이종 코어 혼합 | DSU: L3 + 코히런시 | CMN: 칩 전체 메시

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 / MeshCMN 메시 / NoC
이종 코어없음 (동종)P-core + E-coreX + A(big) + A(LITTLE)
NUMA 분할NPS1/2/4SNC2/4ACPI PPTT
소켓 간xGMI (IF)UPICCIX / CXL / 커스텀
칩렛/타일CCD + IOD 분리EMIB 타일모놀리식 (서버 일부 칩렛)

캐시 계층 · 코히런시 프로토콜

항목AMDIntelARM
L1D/L1I32K/32K (Zen4: 48K/32K)48K/32K (P), 32K/64K (E)코어별 상이
L21MB/코어1.25-2MB/P, 2-4MB/4E256K~2MB/코어
L3/LLC32MB/CCD슬라이스 분산 (1.875MB/코어)DSU L3 + SLC(서버)
코히런시MOESIMESIFMESI / AMBA CHI
디렉토리Probe FilterSnoop FilterHN-F 디렉토리
코히런시 프로토콜 상세: MESI 상태 전환 다이어그램, MOESI/MESIF 비교, 스누핑 vs 디렉토리 방식의 상세 설명은 CPU 캐시 — 코히런시 프로토콜을 참조하세요.

5. 커널의 토폴로지 탐지

x86 CPUID 기반 탐지

x86 커널은 CPUID 명령어를 사용하여 CPU 토폴로지를 탐지합니다. 핵심 Leaf:

Leaf용도제공 정보
0x0BExtended TopologySMT/Core 레벨 ID, 토폴로지 유형
0x1FV2 Extended TopologyModule/Tile/Die 레벨 추가 (SPR+)
0x8000001EAMD 토폴로지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;
}
CPUID 명령어 상세: CPUID Leaf의 전체 목록과 인라인 어셈블리 사용법은 어셈블리 — CPUID 기반 토폴로지 탐지를 참조하세요.

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;
}

초기화 흐름

커널 부팅 시 토폴로지 구축 순서:

  1. BSP(Bootstrap Processor)에서 identify_cpu() → CPUID/PPTT 파싱
  2. AP(Application Processor) 깨움 → smp_callin()에서 개별 토폴로지 ID 설정
  3. topology_init()/sys/devices/system/cpu/cpuN/topology/ sysfs 노출
  4. 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물리 소켓 ID0
die_id다이(CCD) ID0~11
cluster_id클러스터 ID (ARM, Intel E-core)0
core_id물리 코어 ID0~95
thread_siblingsSMT 형제 CPU 비트맵00000003
thread_siblings_listSMT 형제 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_CPUCAPACITYCPU 0 ↔ CPU 96
MC (Multi-Core)L3 공유 코어SD_SHARE_PKG_RESOURCESCCD 내 8코어
CL (Cluster)L2 공유 클러스터SD_SHARE_CLS_RESOURCESIntel E-core 4개
DIE같은 다이Intel Tile
NUMANUMA 노드SD_NUMANPS 분할 영역
로드 밸런싱 범위: 스케줄러는 낮은 레벨(SMT)부터 높은 레벨(NUMA)로 올라가며 태스크를 분산합니다. 같은 MC 내에서 밸런싱하면 L3 캐시 히트율을 유지할 수 있고, NUMA 경계를 넘으면 메모리 지연이 증가합니다.
💡

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
Linux sched_domain 계층 (AMD EPYC NPS4 예시) NUMA domain (node 0..3) — SD_NUMA DIE domain (node 0) DIE domain (node 1) MC: CCD0 (L3 32MB) MC: CCD1 (L3 32MB) MC: CCD2 (L3 32MB) MC: CCD3 (L3 32MB) C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15 T0 T1 SMT 스케줄링 도메인 우선순위 (밸런싱 비용 증가 →) SMT (L1/L2 공유) → MC (L3 공유) → DIE (소켓 내) → NUMA (메모리 지역성)

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.cCPUID 기반 토폴로지 탐지, detect_extended_topology()
arch/x86/kernel/cpu/amd.cAMD 전용 토폴로지 (CPUID 0x8000001E)
arch/x86/kernel/cpu/intel.cIntel 전용 토폴로지, Thread Director
arch/x86/kernel/smpboot.cSMP 부팅, AP 초기화, sibling map
arch/x86/kernel/cpu/cacheinfo.cCPUID 기반 캐시 토폴로지

ARM64 토폴로지

파일역할
arch/arm64/kernel/topology.cARM64 토폴로지 초기화, PPTT 파싱
drivers/base/arch_topology.c아키텍처 공통: cpu-capacity, freq-factor
drivers/acpi/pptt.cACPI PPTT 테이블 파서
drivers/perf/arm-cmn.cCMN 메시 PMU 드라이버

스케줄러 토폴로지

파일역할
kernel/sched/topology.csched_domain 구축, build_sched_domains()
kernel/sched/fair.cCFS 로드 밸런싱, EAS, ASYM_PACKING
include/linux/topology.h토폴로지 매크로/함수 선언
drivers/thermal/intel/intel_hfi.cIntel 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
주의: 프로덕션 환경에서 ftrace를 활성화하면 오버헤드가 발생합니다. 디버깅/프로파일링 목적으로만 사용하고, 측정 후 반드시 비활성화하세요.