Intel PCM (Performance Counter Monitor) 완전 가이드

Intel PCM(Performance Counter Monitor)을 사용해 CPU 코어·언코어·메모리·PCIe·전력을 실시간 통합 계측하는 방법을 다룹니다. pcm-memory/pcm-pcie/pcm-tpmi/pcm-power를 중심으로 CXL 대역폭 분석, NUMA 불균형 진단, 플랫폼별 카운터 해석, Grafana/Prometheus 대시보드 연동, perf/pmu-tools와 결합한 TMA Top-Down 병목 분석까지 Sapphire/Emerald/Granite Rapids 환경 기준으로 실무 흐름에 맞춰 설명합니다.

⚠️

전제 조건: Intel PCM은 Intel CPU 전용 도구입니다. MSR 레지스터 직접 접근을 위해 root 권한(또는 CAP_SYS_RAWIO)과 msr 커널 모듈이 필요합니다. Secure Boot 환경에서는 perf_event 모드(PCM_USE_PERF=1) 또는 TPMI(6.3+) 경로를 사용하세요.

💡

일상 비유: 자동차 계기판처럼, PCM은 CPU(엔진 회전수·연비), 메모리(연료 흐름), PCIe(도로 통행량), 전력(연료 소비량)의 모든 수치를 한눈에 보여주는 하드웨어 계기판입니다. perf가 특정 부품(함수/프로세스)을 분석한다면, PCM은 시스템 전체 하드웨어 상태를 한 화면에 표시합니다.

핵심 요약

  • PCM vs perf: perf는 프로세스/함수 수준 프로파일링, PCM은 시스템 전체 언코어 카운터 모니터링
  • 3가지 접근 경로: MSR 드라이버(/dev/cpu/*/msr), perf_event_open(), sysfs/MMIO(TPMI)
  • pcm-memory: 소켓/채널별 DRAM 대역폭을 iMC 카운터로 실시간 측정, BW 포화 진단
  • pcm-tpmi: Sapphire Rapids+에서 MMIO 기반 언코어 접근 (Secure Boot 호환)
  • CXL 모니터링: pcm-pcie -cxl로 CXL Type 1/2/3 장치의 대역폭/레이턴시 측정
  • REST API / Grafana: pcm-sensor-server로 Prometheus 메트릭 노출, Grafana 대시보드 연동
  • TMA 연계: pcm + toplev 조합으로 Frontend/Backend/Bad Speculation 자동 분류
  • 커널 인프라: msr, intel_uncore, intel_rapl, intel_vsec/tpmi 드라이버 기반

단계별 이해

  1. 설치: GitHub 소스 빌드 또는 패키지 설치, msr 모듈 로드, NMI watchdog 비활성화
  2. 기본 모니터링: sudo pcm으로 코어별 IPC/캐시 히트율/주파수/온도 확인
  3. 메모리 BW: sudo pcm-memory로 소켓별 읽기/쓰기 대역폭 → 이론값 대비 포화율 계산
  4. PCIe/CXL: sudo pcm-pcie(표준) / sudo pcm-pcie -cxl(CXL 장치)로 인바운드/아웃바운드 BW
  5. TPMI 활용: sudo pcm-tpmi로 Sapphire Rapids+ 언코어 카운터 접근 (MSR 불필요)
  6. Grafana 연동: sudo pcm-sensor-server → Prometheus scrape → Grafana 대시보드 임포트
  7. TMA 분석: toplev.py -l1~l3으로 파이프라인 병목 대분류 → PCM으로 하드웨어 수치 확인
  8. 진단 시나리오: IPC 저하 → 메모리 BW 포화, 주파수 스로틀링, NUMA 불균형, LLC 쓰레싱 순으로 확인

PCM 개요 및 아키텍처

Intel PCM은 Intel이 개발한 오픈소스 성능 모니터링 도구 모음으로, CPU 코어 성능 카운터, 메모리 대역폭, QPI/UPI 링크 사용률, PCIe 대역폭, 전력 소비량 등을 실시간으로 측정합니다. perf가 커널에 내장된 범용 프로파일링 프레임워크라면, PCM은 Intel 플랫폼에 특화된 시스템 수준 하드웨어 모니터링 도구입니다.

ℹ️

PCM vs perf: perf는 커널 perf_event 서브시스템을 통해 PMU에 접근하며 프로세스/함수 수준 프로파일링에 강합니다. 반면 PCM은 MSR/PCI config 레지스터에 직접 접근하여 언코어(Uncore) 카운터 — 메모리 컨트롤러, QPI/UPI 링크, PCIe, 전력 등 코어 외부 리소스 — 를 포함한 시스템 전체 관점의 모니터링에 특화되어 있습니다.

PCM은 세 가지 경로로 하드웨어 카운터에 접근합니다:

User Space pcm (Core 카운터) pcm-memory (메모리 BW) pcm-pcie (PCIe BW) pcm-power (전력/온도) pcm-latency (메모리 레이턴시) pcm-sensor-server (REST API/Grafana) Kernel Space /dev/cpu/*/msr (MSR) perf_event_open() (PMU) sysfs / MMIO (TPMI) Hardware (CPU / Uncore) Core PMU PMC, Fixed CTR Uncore PMU CBox, iMC, UPI 메모리 컨트롤러 iMC 카운터 RAPL PKG/DRAM 에너지 PCIe / CXL IIO 카운터
접근 경로대상 카운터커널 요구사항용도
MSR 드라이버Core PMU, Fixed CTR, RAPLmsr 커널 모듈코어별 성능 카운터, 전력 측정
perf_eventCore/Uncore PMUCONFIG_PERF_EVENTSperf 서브시스템 경유 (권한 제어 용이)
sysfs/MMIOTPMI, PCI config spaceTPMI 드라이버 (6.3+)언코어 카운터, PCIe/CXL 모니터링

설치 및 빌드

# 소스에서 빌드 (GitHub)
git clone --recursive https://github.com/intel/pcm.git
cd pcm
mkdir build && cd build
cmake ..
cmake --build . --parallel

# 패키지 매니저로 설치 (배포판별)
sudo apt install pcm              # Ubuntu 22.04+ / Debian
sudo dnf install pcm              # Fedora / RHEL 9+

# Docker로 실행 (권한 필요)
docker run --privileged -d \
  --name pcm --ipc=host --pid=host \
  -v /sys:/sys:rw \
  ghcr.io/intel/pcm

커널 모듈 및 접근 권한 설정

PCM은 MSR 레지스터에 직접 접근하므로 msr 커널 모듈과 root 권한(또는 CAP_SYS_RAWIO)이 필요합니다:

# msr 커널 모듈 로드
sudo modprobe msr

# NMI watchdog 비활성화 (PMU 카운터 점유 방지)
# NMI watchdog가 고정 카운터를 사용하면 PCM과 충돌
sudo sysctl kernel.nmi_watchdog=0

# Secure Boot 환경에서 MSR 접근 허용
# /dev/cpu/*/msr 접근이 차단될 경우:
sudo modprobe msr allow_writes=on

# perf_event 기반 접근 사용 시 (MSR 직접 접근 대신)
# PCM은 perf_event 모드도 지원 (-e 옵션 또는 환경변수)
export PCM_USE_PERF=1
sudo sysctl kernel.perf_event_paranoid=-1
⚠️

NMI watchdog 충돌: NMI watchdog는 고정 카운터(INST_RETIRED.ANY)를 점유합니다. PCM 실행 전 nmi_watchdog=0으로 비활성화하지 않으면 카운터 프로그래밍이 실패하거나 부정확한 결과가 나올 수 있습니다. PCM은 시작 시 이 충돌을 자동 감지하고 경고합니다.

핵심 도구 모음

PCM은 목적별로 분리된 여러 도구를 제공합니다. 각 도구는 Intel CPU의 특정 하드웨어 카운터에 최적화되어 있습니다.

pcm: 코어 성능 카운터

기본 도구로, 코어별 IPC(Instructions Per Cycle), L2/L3 캐시 히트율, 분기 예측률 등 핵심 지표를 실시간 표시합니다.

# 기본 실행: 1초 간격으로 코어별 성능 카운터 표시
sudo pcm

# 측정 간격 및 반복 횟수 지정
sudo pcm 0.5 -i=20   # 0.5초 간격, 20회 측정

# CSV 출력 (후처리/시각화용)
sudo pcm 1 -csv=result.csv

# 특정 프로그램 실행 동안 측정
sudo pcm -- ./benchmark

# 코어 이벤트 커스텀 지정 (최대 4개 범용 카운터)
sudo pcm -e core/config=0x2e,config1=0x41,name=LLC_MISSES/

pcm 출력의 주요 지표:

지표설명정상 범위이상 징후
IPCInstructions Per Cycle1.0~4.0< 0.5이면 심각한 메모리 스톨
L2 Hit RatioL2 캐시 히트율> 95%< 80%이면 작업 셋 > L2
L3 Hit RatioL3 (LLC) 캐시 히트율> 80%< 50%이면 메모리 대역폭 확인 필요
FREQ실제 동작 주파수 (GHz)부스트 근처기본 클럭 이하이면 전력/열 제한
TEMP코어 온도 (°C)< TjMax-10TjMax 도달 시 스로틀링
INST은퇴된 명령어 수워크로드 의존코어 간 불균형 → 부하 분산 문제
AFREQActive Frequency (활성 시 주파수)≈ Max Turbo기본 클럭 근처이면 전력 제한
L3MISSL3 캐시 미스 횟수워크로드 의존높으면 메모리 BW 병목

pcm-memory: 메모리 대역폭 모니터링

소켓/채널별 메모리 대역폭(Read/Write/Total)을 iMC(Integrated Memory Controller) 카운터로 실시간 측정합니다. NUMA 환경에서 메모리 병목 진단에 매우 중요한 지표입니다.

# 소켓/채널별 메모리 대역폭 측정
sudo pcm-memory

# 0.5초 간격, 파일 출력
sudo pcm-memory 0.5 -csv=mem_bw.csv

# 특정 소켓만 모니터링
sudo pcm-memory -s 0  # 소켓 0만

출력 예시:

SocketRead (GB/s)Write (GB/s)PMM ReadPMM WriteTotal (GB/s)
045.212.8N/AN/A58.0
143.811.5N/AN/A55.3
System89.024.3N/AN/A113.3
💡

메모리 대역폭 포화 판단: 이론적 최대 대역폭은 채널 수 × DDR 전송률 × 8바이트로 계산됩니다. 예: 6채널 DDR5-4800 = 6 × 4800MT/s × 8B ≈ 230 GB/s. 측정값이 이론값의 70% 이상이면 메모리 BW 포화 상태입니다. perf stat -e LLC-load-misses와 함께 확인하세요.

pcm-pcie: PCIe 대역폭 모니터링

IIO(I/O 유닛) 언코어 카운터를 통해 PCIe 포트별 인바운드/아웃바운드 대역폭을 측정합니다. NVMe SSD, GPU, 네트워크 카드 등의 I/O 병목 진단에 사용합니다.

# PCIe 포트별 대역폭 (GB/s)
sudo pcm-pcie

# 이벤트 모드: Part0~Part3 상세 분류
sudo pcm-pcie -e

# 특정 BDF (Bus:Device.Function) 필터링
sudo pcm-pcie -B 0x3a:0x00.0

# CSV 출력
sudo pcm-pcie 1 -csv=pcie_bw.csv

# CXL 메모리 대역폭 모니터링 (지원 플랫폼)
sudo pcm-pcie -cxl

pcm-power: 전력 및 열 모니터링

RAPL(Running Average Power Limit) MSR과 온도 센서를 통해 패키지/DRAM/PP0/PP1별 전력 소비와 코어 온도, C-State 상주 비율을 실시간으로 표시합니다.

# 전력/온도/C-State 모니터링
sudo pcm-power

# 출력 예시:
# Package 0: Consumed energy (Joules): 85.2 | Thermal headroom: 23°C
# Package 0: C2 residency: 45.2% | C6 residency: 32.1%
# DRAM energy: 12.8 J

# 전력 변화 추세 관찰 (CSV)
sudo pcm-power 1 -csv=power.csv

pcm-latency: 메모리 레이턴시 측정

메모리 접근 레이턴시를 측정합니다. NUMA 환경에서 로컬/원격 메모리 접근 지연 차이를 정량적으로 파악할 수 있습니다.

# 메모리 레이턴시 측정
sudo pcm-latency

# 특정 소켓 대상
sudo pcm-latency -s 0

pcm-numa: NUMA 트래픽 분석

NUMA 환경에서 로컬/원격 메모리 접근 비율을 측정하여 메모리 배치 최적화 기회를 식별합니다.

# NUMA 로컬/원격 메모리 접근 비율 측정
sudo pcm-numa

# 출력 예시:
# Socket 0: Local Memory Accesses: 95.2% | Remote: 4.8%
# Socket 1: Local Memory Accesses: 87.3% | Remote: 12.7%  ← 최적화 필요

# NUMA 최적화 확인: 원격 접근이 10% 이상이면
# numactl --membind 또는 cpuset으로 바인딩 조정 필요

pcm-iio: I/O 유닛 통계

IIO(I/O 유닛) 스택별 인바운드/아웃바운드 트래픽을 상세 분석합니다. PCIe 디바이스와 CPU 소켓 간 데이터 흐름을 파악합니다.

# I/O 유닛(IIO) 스택별 트래픽
sudo pcm-iio

# CSV 출력
sudo pcm-iio 1 -csv=iio.csv

pcm-raw: Raw 카운터 프로그래밍

사전 정의 도구로 측정할 수 없는 커스텀 이벤트를 JSON 기반 이벤트 정의 파일로 프로그래밍합니다. Intel SDM의 이벤트 코드를 직접 지정할 수 있습니다.

# JSON 이벤트 정의 파일 사용
sudo pcm-raw -e events.json

# 이벤트 정의 예시 (events.json):
# {
#   "core": {
#     "programmable": [
#       { "name": "L2_MISS", "event": "0x2e", "umask": "0x41" },
#       { "name": "DTLB_MISS", "event": "0x08", "umask": "0x20" }
#     ]
#   }
# }

# PCM 배포에 포함된 사전 정의 이벤트
ls /usr/share/pcm/PMURegisterDeclarations/
# → SPR/ ICX/ SKX/ ... (마이크로아키텍처별 이벤트 파일)

pcm-sensor-server: REST API 서버

pcm-sensor-server는 PCM 데이터를 HTTP/HTTPS REST API로 노출하여, Grafana, Prometheus, Telegraf 등 외부 모니터링 시스템과 통합합니다. 자세한 설정은 Grafana/Prometheus 대시보드 섹션을 참고하세요.

# REST API 서버 시작 (기본 포트: 9738)
sudo pcm-sensor-server

# HTTPS + 포트 지정
sudo pcm-sensor-server -p 19738 --https 443 \
  --key server.key --cert server.crt

# JSON 데이터 조회
curl -s http://localhost:9738/metrics | head -20

pcm-tpmi 및 신규 플랫폼

Sapphire Rapids(SPR) 이후 Intel 서버 플랫폼은 TPMI(Topology Aware Register and PM Interface)를 도입했습니다. TPMI는 MSR 대신 MMIO 기반으로 동작하여 Secure Boot 환경에서도 사용 가능하며, 더 세밀한 토폴로지 인식 레지스터 접근을 제공합니다.

TPMI 아키텍처

TPMI(Topology Aware Register and PM Interface)는 Intel Sapphire Rapids에서 도입된 새로운 하드웨어 인터페이스로, 다음과 같은 특징을 갖습니다:

# TPMI 기반 언코어 카운터 접근
sudo pcm-tpmi

# TPMI 지원 확인
ls /sys/bus/auxiliary/devices/ | grep intel_vsec
# intel_vsec 드라이버가 로드되어 있으면 TPMI 지원

# TPMI 관련 커널 드라이버 확인
lsmod | grep -E "intel_vsec|intel_tpmi|intel_pmt"
# intel_vsec: VSEC 기반 플랫폼 인터페이스
# intel_tpmi: TPMI 레지스터 MMIO 접근 (6.3+)
# intel_pmt_telemetry: PMT 텔레메트리

# TPMI sysfs 경로
ls /sys/bus/auxiliary/devices/intel_vsec.tpmi-*/
# → header, guid, num_entries, cap_offset 등

Sapphire Rapids / Emerald Rapids / Granite Rapids

PCM은 최신 Intel 서버 마이크로아키텍처를 완전히 지원합니다. 플랫폼별 주요 차이점:

플랫폼코드명출시PCM 주요 기능TPMI
Sapphire RapidsSPR (Xeon 4th Gen)2023HBM 모니터링, CXL 1.1, TPMI 최초 도입, AMX 카운터✅ 지원
Emerald RapidsEMR (Xeon 5th Gen)2024DDR5 6400MT/s 대역폭, 개선된 언코어 PMU, UPI 3.0✅ 지원
Granite RapidsGNR (Xeon 6th Gen)2024다수 다이 통합 (P-die + E-die), CXL 2.0, 확장 IIO✅ 지원
Ice Lake-SPICX (Xeon 3rd Gen)2021UPI 2.0, PCIe Gen4, DDR4 채널 × 8
Skylake-SPSKX/CLX2017~UPI 링크 카운터, 기본 iMC 카운터
# Emerald Rapids: 향상된 메모리 대역폭 모니터링
# 소켓당 최대 12채널 DDR5-6400 ≈ 614 GB/s 이론값
sudo pcm-memory 0.5
# → 'Total Memory BW' 가 600+ GB/s에 근접하면 BW 포화 임박

# Granite Rapids: P-die / E-die 혼합 모니터링
# -die 옵션으로 다이별 분리 통계 (PCM 2.0+)
sudo pcm -die 0   # P-die 전용
sudo pcm -die 1   # E-die 전용

# SPR AMX (Advanced Matrix Extensions) 카운터
sudo pcm-raw -e /usr/share/pcm/PMURegisterDeclarations/SPR/core.json
# → AMX_OPS_SPEC, TMUL_COMPUTED_8BIT 등 행렬 연산 카운터
ℹ️

Sapphire Rapids HBM 모니터링: HBM(High Bandwidth Memory) 탑재 SPR-HBM 모델에서는 pcm-memory가 DDR5 채널과 HBM 채널을 구분하여 표시합니다. HBM은 소켓당 최대 1 TB/s의 이론 대역폭을 제공하며, HBM Read/Write 컬럼으로 별도 확인합니다.

CXL 메모리 모니터링

CXL(Compute Express Link)은 PCIe 물리 계층 위에 구축된 캐시/메모리 일관성 프로토콜로, CPU와 가속기/메모리 확장 장치 간의 고속 인터코넥트를 제공합니다. PCM은 IIO 카운터와 pcm-pcie -cxl 모드를 통해 CXL 장치 대역폭과 레이턴시를 측정합니다.

CXL 장치 유형과 PCM 지원

Host CPU (SPR / EMR / GNR) CXL Root Port (IIO) CXL Switch (CXL 2.0+, 선택사항) CXL Type 1 가속기 (캐시 공유) 예: SmartNIC, FPGA 캐시는 있음, 로컬 메모리 없음 CXL Type 2 GPU/가속기 (캐시+메모리) 예: CXL-attached GPU 캐시 + 로컬 메모리 모두 CXL Type 3 메모리 확장 장치 예: DRAM/PMEM 모듈 메모리 전용, 캐시 없음 PCM CXL 모니터링 pcm-pcie -cxl: IIO 포트별 CXL 대역폭 (Read/Write GB/s) pcm-latency: CXL 메모리 접근 레이턴시 (ns 단위) pcm-numa: CXL 노드 로컬/원격 접근 비율 → NUMA topology 반영
CXL 유형특징Linux NUMA 노드PCM 도구대역폭 기준
Type 1가속기, 캐시 공유, 로컬 메모리 없음별도 노드 없음pcm-pcie -cxlPCIe Gen5 ×16 ≈ 128 GB/s
Type 2가속기 + 캐시 + 로컬 메모리별도 NUMA 노드pcm-pcie -cxl, pcm-numa장치 의존적
Type 3메모리 확장 전용 (DRAM/PMEM)별도 NUMA 노드pcm-memory, pcm-latencyCXL 1.1 ≈ 40 GB/s (Gen4 ×8)

CXL 모니터링 실전 사용법

# 1. CXL 장치 감지 확인
ls /sys/bus/cxl/devices/
# → mem0, mem1 등 CXL 메모리 장치 나열
# → decoder0.0, region0 등 CXL 리전 표시

# 2. CXL 대역폭 모니터링 (IIO 카운터 기반)
sudo pcm-pcie -cxl
# → CXL_UPSTREAM_BANDWIDTH, CXL_DOWNSTREAM_BANDWIDTH 표시
# → IIO 스택별 CXL 포트 인바운드/아웃바운드 GB/s

# 3. CXL Type 3 메모리 대역폭 (pcm-memory)
# CXL 메모리는 NUMA 노드로 노출됨 (node 2, 3 등)
sudo pcm-memory
# → DDR 채널 외 'CXL Port' 행 확인

# 4. CXL 메모리 레이턴시 측정
sudo pcm-latency
# → Local DDR: ~75ns, Remote DDR: ~130ns, CXL: ~200-300ns (장치/토폴로지 의존)

# 5. NUMA 통계로 CXL 접근 비율 확인
sudo pcm-numa
# → CXL 노드 접근이 많으면 numactl --membind 로 바인딩 최적화

# 6. CXL 노드 정보 (커널 통합 정보)
numactl --hardware
# → CXL Type 3는 별도 NUMA 노드 (distance 매우 높음)
cat /sys/devices/system/node/node2/meminfo
# → CXL 메모리 노드의 MemTotal, MemFree 확인
💡

CXL 레이턴시 특성: CXL Type 3 메모리는 로컬 DDR 대비 약 2~4배 높은 레이턴시(200~300ns)를 가집니다. pcm-latency로 CXL 노드 레이턴시를 측정하고, 레이턴시 민감 데이터는 numactl --membind=0으로 로컬 DDR에 할당하세요. 레이턴시 허용 가능한 대용량 데이터(캐시/버퍼)는 CXL 노드를 활용합니다.

Grafana/Prometheus 대시보드

pcm-sensor-server는 PCM의 모든 측정값을 HTTP REST API로 노출합니다. Prometheus가 메트릭을 수집하고, Grafana가 시각화합니다. PCM 소스에는 사전 정의된 Grafana 대시보드 JSON이 포함되어 있어 즉시 임포트가 가능합니다.

스택 구성 — docker-compose

# docker-compose.yml — PCM 모니터링 스택
version: '3.8'
services:
  pcm:
    image: ghcr.io/intel/pcm
    container_name: pcm-sensor
    privileged: true
    pid: host
    ipc: host
    volumes:
      - /sys:/sys:rw
      - /proc:/proc:ro
    command: ["pcm-sensor-server", "-p", "9738"]
    ports:
      - "9738:9738"
    restart: unless-stopped

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-storage:/var/lib/grafana
    restart: unless-stopped

volumes:
  grafana-storage:
# prometheus.yml — PCM 스크레이프 설정
global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'intel-pcm'
    static_configs:
      - targets: ['pcm:9738']
    metrics_path: '/prometheus'
    scrape_timeout: 4s

REST API 엔드포인트

pcm-sensor-server가 노출하는 주요 API 엔드포인트:

엔드포인트설명형식
GET /전체 PCM 메트릭 (JSON 계층 구조)JSON
GET /prometheusPrometheus 형식 메트릭text/plain
GET /package/{n}패키지 n의 상세 메트릭JSON
GET /core/{n}코어 n의 상세 메트릭JSON
GET /memory메모리 대역폭 메트릭JSON
GET /pciePCIe 대역폭 메트릭JSON
# Prometheus 메트릭 조회 예시
curl -s http://localhost:9738/prometheus | grep -E "pcm_(ipc|memory|freq)"
# pcm_ipc{socket="0",core="0"} 2.34
# pcm_memory_read_bandwidth{socket="0"} 45.2
# pcm_memory_write_bandwidth{socket="0"} 12.8
# pcm_freq_mhz{socket="0",core="0"} 3800

# JSON 전체 메트릭 구조 확인
curl -s http://localhost:9738/ | python3 -m json.tool | head -40

Grafana 대시보드 임포트

# PCM 소스의 Grafana 대시보드 JSON 위치
ls /path/to/pcm/grafana/
# → PCM-Core-Metrics.json        (코어별 IPC, 캐시, 주파수)
# → PCM-Memory-Bandwidth.json    (소켓/채널별 메모리 BW)
# → PCM-Power-Thermal.json       (전력 소비, 온도, C-State)
# → PCM-PCIe-Bandwidth.json      (PCIe 포트별 대역폭)

# Grafana API로 자동 임포트
curl -X POST http://admin:admin@localhost:3000/api/dashboards/import \
  -H 'Content-Type: application/json' \
  -d @PCM-Core-Metrics.json
💡

Grafana 알람 설정: Prometheus + Grafana 조합에서 알람 규칙 예시: pcm_memory_read_bandwidth{socket="0"} > 200 (메모리 BW 포화), pcm_ipc < 0.5 (IPC 급락), pcm_freq_mhz < 2000 (주파수 스로틀링). Alertmanager를 통해 Slack/PagerDuty로 알림을 발송합니다.

실전 진단 시나리오

PCM 도구를 결합하여 실제 성능 문제를 단계별로 진단하는 시나리오입니다.

시나리오 1: 메모리 대역폭 포화 진단

애플리케이션이 CPU 사용률은 높지만 IPC가 낮은 경우, 메모리 대역폭 포화가 원인일 수 있습니다:

# 1단계: IPC 확인 → 메모리 바운드 여부 판단
sudo pcm 1 -i=5
# → IPC < 1.0 + L3 Hit Ratio < 50% → 메모리 바운드 의심

# 2단계: 메모리 대역폭 측정
sudo pcm-memory 0.5
# → Read BW가 이론값의 70% 이상이면 BW 포화
# → 채널 간 불균형이 크면 DIMM 구성 확인

# 3단계: NUMA 배치 확인
sudo pcm-numa
# → Remote Access > 10%이면 메모리 배치 최적화
# → numactl --membind=0 ./app 으로 로컬 바인딩

# 4단계: perf로 핫스팟 함수의 LLC 미스 확인
perf record -e LLC-load-misses:pp -c 10000 -- ./app
perf report

시나리오 2: PCIe I/O 병목 진단

# NVMe/GPU가 예상 성능에 미달할 때

# 1단계: PCIe 대역폭 측정
sudo pcm-pcie 1
# → 디바이스별 인바운드/아웃바운드 BW 확인
# → Gen4 x16: 이론 31.5 GB/s, 실측이 50% 미만이면 문제

# 2단계: IIO 스택별 상세 분석
sudo pcm-iio 1
# → 어느 IIO 스택에서 병목이 발생하는지 파악

# 3단계: 전력 제한 확인 (전력 제한으로 I/O 성능 저하 가능)
sudo pcm-power 1
# → PKG 전력이 TDP 근처이면 전력 스로틀링

시나리오 3: 코어 주파수 스로틀링 진단

# 성능이 간헐적으로 저하될 때 (열/전력 제한 의심)
sudo pcm 0.5 -csv=freq_trace.csv -i=60
# → FREQ/AFREQ 컬럼에서 주파수 변동 추적
# → TEMP가 TjMax에 근접하면 열 스로틀링
# → C6 residency가 높으면 idle 상태 비율 과다

# turbostat 병행 (PCM과 보완적)
sudo turbostat --interval 1 --show Core,CPU,Avg_MHz,Busy%,Bzy_MHz,PkgWatt
# Busy% 100%인데 Bzy_MHz < Max Turbo이면 전력/열 제한

시나리오 4: NUMA 불균형 진단

다소켓 서버에서 특정 소켓만 메모리 BW가 높거나, 원격 메모리 접근이 많은 경우:

# 1단계: 소켓별 메모리 대역폭 불균형 확인
sudo pcm-memory 1
# → Socket 0: 90 GB/s, Socket 1: 10 GB/s → 심각한 불균형
# → 원인: 특정 소켓에 스레드가 집중되거나 메모리가 쏠림

# 2단계: NUMA 로컬/원격 접근 비율 상세 확인
sudo pcm-numa 1
# → Remote Access > 20%이면 매우 비효율적

# 3단계: 프로세스 NUMA 배치 확인
numastat -p $(pgrep -d, myapp)
# → 프로세스가 사용하는 각 NUMA 노드 메모리량 표시

# 4단계: 해결 — numactl로 CPU+메모리 바인딩
numactl --cpunodebind=0 --membind=0 ./myapp
# 또는 인터리브로 균등 분산:
numactl --interleave=all ./myapp

# 5단계: Automatic NUMA Balancing 활성화 확인
cat /proc/sys/kernel/numa_balancing
# 0이면 비활성 → echo 1 로 활성화 (자동 페이지 마이그레이션)

시나리오 5: LLC 쓰레싱 진단

L3 캐시 히트율이 낮고 메모리 대역폭이 높은 경우, 여러 프로세스 간 LLC 경합(쓰레싱)이 원인일 수 있습니다:

# 1단계: LLC 쓰레싱 여부 확인 (IPC + L3 히트율)
sudo pcm 1
# → L3 Hit Ratio < 40% + pcm-memory가 높은 BW → LLC 쓰레싱 의심

# 2단계: perf c2c로 캐시 라인 경합 확인
sudo perf c2c record -- ./workload
sudo perf c2c report --call-graph none | head -30
# → 'Shared Cache Line Distribution' 에서 경합 심한 캐시 라인 확인

# 3단계: Intel RDT(Resource Director Technology)로 LLC 파티션
# 코어 별 LLC 사용량을 resctrl로 제한 (Intel CAT)
mount -t resctrl resctrl /sys/fs/resctrl
mkdir /sys/fs/resctrl/workload_A
echo "L3:0=0x0ff" > /sys/fs/resctrl/workload_A/schemata  # 하위 8way 할당
echo $(pgrep workload_A) > /sys/fs/resctrl/workload_A/tasks

# 4단계: 캐시 친화적 재구성
# → 핫 데이터 구조체에 __cacheline_aligned 적용
# → 스레드 간 공유 데이터 최소화 (false sharing 제거)
# → 큰 배열을 청크로 나눠 한 번에 LLC에 맞게 처리 (타일링)

시나리오 6: C-State 레지던시 분석

서버 워크로드에서 레이턴시 급등(jitter)이 발생하는 경우, 깊은 C-State에 진입한 코어가 재활성화되는 시간이 원인일 수 있습니다:

# 1단계: C-State 분포 확인
sudo pcm-power 1 -csv=cstate.csv
# → C6/C7 residency > 50%이면 레이턴시 민감 워크로드에 위험

# 2단계: turbostat으로 코어별 C-State 상세 확인
sudo turbostat --interval 1 \
  --show Core,CPU,Busy%,C1%,C3%,C6%,C7%,PkgWatt
# → 특정 코어가 C7에 자주 진입하면 wake-up latency 수십 µs 발생

# 3단계: C-State 제한으로 레이턴시 개선
# 방법 1: 커널 파라미터로 전역 제한
# intel_idle.max_cstate=1 (grub GRUB_CMDLINE_LINUX에 추가)

# 방법 2: per-CPU C-State 제한 (런타임)
cpupower idle-set -D 1  # 모든 코어 C-State ≤ C1으로 제한

# 방법 3: 특정 코어만 C-State 제한
echo 1 > /sys/devices/system/cpu/cpu0/cpuidle/state2/disable  # C6 비활성화

# 4단계: 결과 검증
sudo pcm-power 1
# → C6 residency ≈ 0% 확인 → 레이턴시 측정으로 jitter 개선 확인

TMA Top-Down 분석 연계

Intel의 Top-Down Microarchitecture Analysis (TMA) 방법론은 CPU 파이프라인의 병목을 4개 대분류(Frontend Bound, Backend Bound, Bad Speculation, Retiring)로 분류합니다. PCM과 pmu-tools/toplev을 결합하면 체계적인 병목 분석이 가능합니다.

Pipeline Slots (100%) Frontend Bound Bad Speculation Backend Bound Retiring Fetch Latency Fetch BW Branch Mispr. Machine Clears Memory Bound Core Bound Base Micro Seq. L1/L2/L3 Bound DRAM Bound Store Bound pcm → IPC/L3 히트율 | pcm-memory → DRAM BW | toplev → TMA Level 1~6 자동 분류
# pmu-tools 설치
git clone https://github.com/andikleen/pmu-tools.git
cd pmu-tools

# toplev: TMA Level 1 (대분류) 분석
sudo python3 toplev.py --core S0-C0 -l1 -v -- ./benchmark
# 출력: FE(Frontend) 30%, BE(Backend) 45%, BadSpec 5%, Retiring 20%
# → Backend Bound가 지배적 → 메모리/코어 바운드 분석 필요

# Level 2: Backend Bound 상세 분해
sudo python3 toplev.py --core S0-C0 -l2 -v -- ./benchmark
# → Memory Bound 35%, Core Bound 10%

# Level 3+: Memory Bound 세부 원인
sudo python3 toplev.py --core S0-C0 -l3 --nodes '!+Memory*' -v -- ./benchmark
# → L3 Bound 8%, DRAM Bound 22%, Store Bound 5%
# → pcm-memory로 DRAM BW 포화 확인

# PCM + toplev 병행 워크플로
# 1. pcm: 전체 시스템 IPC/캐시/주파수 개요 → 이상 징후 파악
# 2. toplev -l1~l3: 병목 카테고리 좁히기
# 3. pcm-memory/pcm-pcie: 구체적 하드웨어 병목 수치 확인
# 4. perf record + annotate: 함수/명령어 수준 최적화

PCM vs 대안 도구 비교

도구제공자카운터 접근강점제한
Intel PCMIntel (오픈소스)MSR, perf_event, MMIO언코어 카운터 (iMC, UPI, IIO) 통합, REST API, CXL 지원Intel CPU 전용
perf커널 내장perf_event범용 프로파일링, 프로세스/함수 수준 분석언코어 카운터 설정 복잡
turbostat커널 소스 포함MSR주파수/전력/C-State 특화, 커널과 함께 배포성능 카운터 제한적
pmu-tools (toplev)Andi Kleenperf 위에 구축Top-Down 마이크로아키텍처 분석 (TMA) 자동화설정 복잡, Intel 전용
likwidRRZE (독일)MSR, perf_eventIntel + AMD 지원, 그룹 기반 측정언코어 카운터 PCM보다 제한적
AMD uProfAMDMSR, perf_eventAMD 전용 언코어 카운터, Infinity Fabric 모니터링AMD CPU 전용

커널 드라이버 및 관련 소스

PCM이 내부적으로 사용하는 커널 인프라:

커널 드라이버/인터페이스경로역할
msr 모듈arch/x86/kernel/msr.c/dev/cpu/N/msr 문자 장치 제공
intel_uncore PMUarch/x86/events/intel/uncore*.cperf 서브시스템에 언코어 PMU 등록
intel_rapldrivers/powercap/intel_rapl_*.cRAPL 전력 측정 (powercap 프레임워크)
intel_vsec/tpmidrivers/platform/x86/intel/tpmi.cTPMI 레지스터 MMIO 접근 (6.3+)
intel-cstate PMUarch/x86/events/intel/cstate.cC-State 상주 시간 카운터
PCI config space/sys/bus/pci/devices/*/config언코어 PCI 레지스터 접근 (iMC, UPI)
/* PCM이 MSR을 읽는 커널 경로 (arch/x86/kernel/msr.c) */
static ssize_t msr_read(struct file *file, char __user *buf,
                       size_t count, loff_t *ppos)
{
    u32 __user *tmp = (u32 __user *)buf;
    u32 data[2];
    u32 reg = *ppos;       /* MSR 주소 = file offset */
    int cpu = iminor(file->f_path.dentry->d_inode);
    int err;

    /* 해당 CPU에서 RDMSR 실행 */
    err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]);
    if (err)
        return -EIO;

    if (copy_to_user(tmp, &data, 8))
        return -EFAULT;
    return 8;
}

/* PCM의 실제 MSR 읽기 (user space → /dev/cpu/N/msr) */
/* pread(fd, &data, sizeof(data), MSR_ADDR) */
/* 예: pread(fd, &val, 8, 0x38F) → IA32_PERF_GLOBAL_CTRL */
# PCM에 필요한 커널 설정
CONFIG_X86_MSR=m                   # /dev/cpu/*/msr (필수)
CONFIG_PERF_EVENTS=y               # perf_event 모드 사용 시
CONFIG_INTEL_UNCORE=m              # 언코어 PMU (perf_event 경유 시)
CONFIG_INTEL_RAPL=m                # RAPL 전력 측정
CONFIG_INTEL_VSEC=m                # TPMI 지원 (SPR+ 서버)
CONFIG_INTEL_PMT_TELEMETRY=m       # PMT 텔레메트리

# msr 모듈 자동 로드 설정
echo "msr" | sudo tee /etc/modules-load.d/msr.conf
💡

perf_event 모드 vs MSR 직접 접근: PCM_USE_PERF=1 환경 변수를 설정하면 PCM이 MSR 직접 접근 대신 perf_event_open()을 통해 카운터에 접근합니다. 이 모드는 msr 커널 모듈이 불필요하고, perf_event_paranoid로 권한을 세밀하게 제어할 수 있습니다. 다만 일부 언코어 카운터는 perf_event로 접근이 불가하므로 MSR 모드가 더 완전한 데이터를 제공합니다.