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드라이버 기반
단계별 이해
- 설치: GitHub 소스 빌드 또는 패키지 설치,
msr모듈 로드, NMI watchdog 비활성화 - 기본 모니터링:
sudo pcm으로 코어별 IPC/캐시 히트율/주파수/온도 확인 - 메모리 BW:
sudo pcm-memory로 소켓별 읽기/쓰기 대역폭 → 이론값 대비 포화율 계산 - PCIe/CXL:
sudo pcm-pcie(표준) /sudo pcm-pcie -cxl(CXL 장치)로 인바운드/아웃바운드 BW - TPMI 활용:
sudo pcm-tpmi로 Sapphire Rapids+ 언코어 카운터 접근 (MSR 불필요) - Grafana 연동:
sudo pcm-sensor-server→ Prometheus scrape → Grafana 대시보드 임포트 - TMA 분석:
toplev.py -l1~l3으로 파이프라인 병목 대분류 → PCM으로 하드웨어 수치 확인 - 진단 시나리오: 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은 세 가지 경로로 하드웨어 카운터에 접근합니다:
| 접근 경로 | 대상 카운터 | 커널 요구사항 | 용도 |
|---|---|---|---|
| MSR 드라이버 | Core PMU, Fixed CTR, RAPL | msr 커널 모듈 | 코어별 성능 카운터, 전력 측정 |
| perf_event | Core/Uncore PMU | CONFIG_PERF_EVENTS | perf 서브시스템 경유 (권한 제어 용이) |
| sysfs/MMIO | TPMI, PCI config space | TPMI 드라이버 (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 출력의 주요 지표:
| 지표 | 설명 | 정상 범위 | 이상 징후 |
|---|---|---|---|
| IPC | Instructions Per Cycle | 1.0~4.0 | < 0.5이면 심각한 메모리 스톨 |
| L2 Hit Ratio | L2 캐시 히트율 | > 95% | < 80%이면 작업 셋 > L2 |
| L3 Hit Ratio | L3 (LLC) 캐시 히트율 | > 80% | < 50%이면 메모리 대역폭 확인 필요 |
| FREQ | 실제 동작 주파수 (GHz) | 부스트 근처 | 기본 클럭 이하이면 전력/열 제한 |
| TEMP | 코어 온도 (°C) | < TjMax-10 | TjMax 도달 시 스로틀링 |
| INST | 은퇴된 명령어 수 | 워크로드 의존 | 코어 간 불균형 → 부하 분산 문제 |
| AFREQ | Active Frequency (활성 시 주파수) | ≈ Max Turbo | 기본 클럭 근처이면 전력 제한 |
| L3MISS | L3 캐시 미스 횟수 | 워크로드 의존 | 높으면 메모리 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만
출력 예시:
| Socket | Read (GB/s) | Write (GB/s) | PMM Read | PMM Write | Total (GB/s) |
|---|---|---|---|---|---|
| 0 | 45.2 | 12.8 | N/A | N/A | 58.0 |
| 1 | 43.8 | 11.5 | N/A | N/A | 55.3 |
| System | 89.0 | 24.3 | N/A | N/A | 113.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에서 도입된 새로운 하드웨어 인터페이스로, 다음과 같은 특징을 갖습니다:
- MMIO 기반: MSR
RDMSR/WRMSR명령어 대신 메모리 맵 I/O를 사용하여 CSR(Control and Status Register)에 접근 - 토폴로지 인식: 소켓/다이/타일/코어 계층 구조를 인식하는 레지스터 주소 공간 제공
- Secure Boot 호환:
msr드라이버 없이도intel_vsec드라이버를 통해 접근 가능 - 전력 관리 통합: RAPL, SST(Speed Select Technology), ISST 등 전력 관리 기능과 통합
# 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 Rapids | SPR (Xeon 4th Gen) | 2023 | HBM 모니터링, CXL 1.1, TPMI 최초 도입, AMX 카운터 | ✅ 지원 |
| Emerald Rapids | EMR (Xeon 5th Gen) | 2024 | DDR5 6400MT/s 대역폭, 개선된 언코어 PMU, UPI 3.0 | ✅ 지원 |
| Granite Rapids | GNR (Xeon 6th Gen) | 2024 | 다수 다이 통합 (P-die + E-die), CXL 2.0, 확장 IIO | ✅ 지원 |
| Ice Lake-SP | ICX (Xeon 3rd Gen) | 2021 | UPI 2.0, PCIe Gen4, DDR4 채널 × 8 | ❌ |
| Skylake-SP | SKX/CLX | 2017~ | 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 지원
| CXL 유형 | 특징 | Linux NUMA 노드 | PCM 도구 | 대역폭 기준 |
|---|---|---|---|---|
| Type 1 | 가속기, 캐시 공유, 로컬 메모리 없음 | 별도 노드 없음 | pcm-pcie -cxl | PCIe Gen5 ×16 ≈ 128 GB/s |
| Type 2 | 가속기 + 캐시 + 로컬 메모리 | 별도 NUMA 노드 | pcm-pcie -cxl, pcm-numa | 장치 의존적 |
| Type 3 | 메모리 확장 전용 (DRAM/PMEM) | 별도 NUMA 노드 | pcm-memory, pcm-latency | CXL 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 /prometheus | Prometheus 형식 메트릭 | text/plain |
GET /package/{n} | 패키지 n의 상세 메트릭 | JSON |
GET /core/{n} | 코어 n의 상세 메트릭 | JSON |
GET /memory | 메모리 대역폭 메트릭 | JSON |
GET /pcie | PCIe 대역폭 메트릭 | 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을 결합하면 체계적인 병목 분석이 가능합니다.
# 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 PCM | Intel (오픈소스) | MSR, perf_event, MMIO | 언코어 카운터 (iMC, UPI, IIO) 통합, REST API, CXL 지원 | Intel CPU 전용 |
| perf | 커널 내장 | perf_event | 범용 프로파일링, 프로세스/함수 수준 분석 | 언코어 카운터 설정 복잡 |
| turbostat | 커널 소스 포함 | MSR | 주파수/전력/C-State 특화, 커널과 함께 배포 | 성능 카운터 제한적 |
| pmu-tools (toplev) | Andi Kleen | perf 위에 구축 | Top-Down 마이크로아키텍처 분석 (TMA) 자동화 | 설정 복잡, Intel 전용 |
| likwid | RRZE (독일) | MSR, perf_event | Intel + AMD 지원, 그룹 기반 측정 | 언코어 카운터 PCM보다 제한적 |
| AMD uProf | AMD | MSR, perf_event | AMD 전용 언코어 카운터, Infinity Fabric 모니터링 | AMD CPU 전용 |
커널 드라이버 및 관련 소스
PCM이 내부적으로 사용하는 커널 인프라:
| 커널 드라이버/인터페이스 | 경로 | 역할 |
|---|---|---|
msr 모듈 | arch/x86/kernel/msr.c | /dev/cpu/N/msr 문자 장치 제공 |
intel_uncore PMU | arch/x86/events/intel/uncore*.c | perf 서브시스템에 언코어 PMU 등록 |
intel_rapl | drivers/powercap/intel_rapl_*.c | RAPL 전력 측정 (powercap 프레임워크) |
intel_vsec/tpmi | drivers/platform/x86/intel/tpmi.c | TPMI 레지스터 MMIO 접근 (6.3+) |
intel-cstate PMU | arch/x86/events/intel/cstate.c | C-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 모드가 더 완전한 데이터를 제공합니다.