Ch 7: CXL.cache — D2H·H2D 흐름과 coherency state
#한 줄 요약
“CXL.cache는 디바이스가 host 메모리를 native 캐시하게 만들어 PCIe 라운드트립을 회피하는 프로토콜입니다.” — D2H Req (device → host: read·write·invalidate)와 H2D Snoop·Resp·Data가 MESI 기반의 양방향 cache coherency를 유지합니다. Type 1·2 디바이스가 사용하며, Type 1 SmartNIC의 packet metadata 캐싱이 대표적 사용 사례입니다.
Ch 6에서 CXL.io의 PCIe 호환성을 봤습니다. 이 장은 디바이스가 host memory를 native 접근하는 CXL.cache 메커니즘입니다. PCIe DMA의 한계를 넘는 coherent caching이 핵심입니다.
#왜 CXL.cache가 필요한가
기존 PCIe 가속기는 host RAM 접근을 DMA로만 합니다. 문제:
- Round-trip 비용 — 매 access마다 DMA setup·완료
- No caching — 같은 데이터 반복 access도 매번 DMA
- No coherency — host가 cache한 데이터를 device가 못 봄
CXL.cache는 디바이스에 작은 local cache를 두고 host memory의 hot region을 coherent하게 캐시합니다.
| 시나리오 | PCIe DMA | CXL.cache |
|---|---|---|
| 같은 데이터 반복 read | 매번 DMA (느림) | 첫 read 후 cache hit (빠름) |
| Coherency | 없음 (app가 처리) | 자동 (hardware) |
| Latency | 수 µs (DMA) | 수십 ns (cache hit) |
#CXL.cache 메시지 — D2H·H2D
CXL.cache는 양방향 메시지로 동작합니다.
| 방향 | 채널 | 메시지 종류 | 의미 |
|---|---|---|---|
| Device → Host | D2H Req | RdShared·RdOwn·RdAny·CLflushed·Invalidate·… | device가 read·write·invalidate 요청 |
| Device → Host | D2H Resp·Data | response·data return | host snoop 응답·data 반환 |
| Host → Device | H2D Req·Snoop | snoop·invalidate | host가 device cache 동기화 |
| Host → Device | H2D Resp·Data | response·data return | device read 응답·data 반환 |
양방향 모두 Req·Resp·Data 3가지 트래픽. PCIe DMA보다 훨씬 정교한 메시지 set입니다.
#Read 흐름 — Device가 Host 메모리 Read
가장 단순한 D2H read:
| 단계 | 동작 |
|---|---|
| 1 | Device가 cache miss 발생 — addr=X |
| 2 | Device → Host: D2H Req RdShared, addr=X |
| 3 | Host CPU의 cache line 상태 확인 |
| 4 | Host → Device: H2D Resp + H2D Data (64 B) |
| 5 | Device cache에 line 채움, state = Shared |
| 6 | Device 내부 use |
RdShared는 읽기 전용 사본. 만약 device가 write 의도면 RdOwn (exclusive 요청). RdOwn은 host의 다른 sharer를 invalidate.
#Write 흐름 — Device가 Host 메모리 Write
| 단계 | 동작 |
|---|---|
| 1 | Device가 cache line modify 의도 |
| 2 | Device → Host: D2H Req RdOwn, addr=X (exclusive 요청) |
| 3 | Host CPU의 cache에서 다른 sharer invalidate |
| 4 | Host → Device: H2D Resp + H2D Data (line 보냄) |
| 5 | Device cache에 line 채움, state = Modified |
| 6 | Device가 modify, 캐시에 보관 |
| 7 | Eviction 또는 explicit writeback 시 → host로 반환 |
#Snoop 흐름 — Host CPU가 같은 Line Read
Device cache에 modified line이 있는데 host CPU가 같은 line read하면:
| 단계 | 동작 |
|---|---|
| 1 | Host CPU read miss — addr=X (이미 device가 Modified state) |
| 2 | Host → Device: H2D Snoop SnpData, addr=X |
| 3 | Device cache 확인 — Modified line 있음 |
| 4 | Device → Host: D2H Resp + D2H Data (modified data 반환) |
| 5 | Device cache state → Shared (또는 Invalid) |
| 6 | Host CPU가 fresh data 받음 |
이 흐름이 MESI coherency의 핵심. Device·Host 양쪽 cache가 같은 line을 가질 때 coherency 유지.
#Cache State — MESI 변형
CXL.cache는 MESI (Modified·Exclusive·Shared·Invalid)와 그 변형을 지원합니다.
| State | 의미 | Device에서 |
|---|---|---|
| Modified (M) | exclusive + dirty | device가 유일 소유, host RAM과 다름 |
| Exclusive (E) | exclusive + clean | device가 유일 소유, host RAM과 동일 |
| Shared (S) | shared + clean | device·host(들)이 공유 read |
| Invalid (I) | line 없음 | cache eviction 또는 invalidate된 상태 |
추가 state:
| State | 의미 |
|---|---|
| Forward (F) | shared 중 forwarding 책임 갖는 sharer (4-state 변형) |
| Owned (O) | shared but dirty (MOESI 변형) |
어떤 state set을 지원하는지는 디바이스 capability에 따라 다릅니다. 보통 MESI가 최소 baseline.
#Type 1 시나리오 — SmartNIC Packet Metadata
대표적 production sweet spot:
| 시나리오 | 동작 |
|---|---|
| 1 | NIC가 packet 받음, packet header 검사 필요 |
| 2 | Packet metadata는 host RAM에 있음 (routing table·flow state) |
| 3 | NIC가 D2H RdShared로 metadata read |
| 4 | NIC cache에 저장, state = Shared |
| 5 | 다음 packet도 같은 metadata 사용 → cache hit, host 접근 없음 |
| 6 | Host CPU가 routing table update 시 H2D Snoop SnpInv로 NIC cache invalidate |
| 7 | NIC가 다음 packet에 RdShared로 fresh data fetch |
이 패턴이 NIC packet processing throughput을 수십% 향상시킬 수 있습니다 (workload 의존).
#Type 2 시나리오 — Accelerator의 Shared Data
Type 2 GPU·NPU도 CXL.cache를 사용해 host의 shared data에 접근합니다.
| 시나리오 | 동작 |
|---|---|
| LLM weight | host에 보관, GPU가 부분 read·캐시 |
| Tokenization table | host에 보관, GPU·NPU가 read |
| Configuration | host control plane, GPU가 cache |
Type 2는 자체 HBM이 있어 대부분의 hot data는 자기 HBM. CXL.cache는 간헐적으로 필요한 host data를 효율적으로 접근하는 데 활용.
#False Sharing — 최악 시나리오
같은 cache line의 다른 byte를 device와 host가 번갈아 modify하면 cache ping-pong 발생:
| 시간 | Device | Host CPU | 트래픽 |
|---|---|---|---|
| t1 | byte 0 modify | — | D2H RdOwn, line snatched |
| t2 | — | byte 32 modify | H2D Snoop, line snatched back |
| t3 | byte 0 again | — | D2H RdOwn again |
| … | (반복) | (반복) | 매번 BISnp 트래픽 |
throughput이 무너집니다. 해결:
- Cache line padding — 다른 byte를 별도 line으로 분리
- alignas(64) — 구조체 alignment 명시
- 데이터 layout 재설계 — AoS vs SoA 선택
#Linux 측 — CXL.cache 활용
Type 1 디바이스의 CXL.cache는 vendor driver 내부에서 사용. 별도 sysfs 노출 없음.
# Type 1 NIC가 attach되면 lspci에 보이지만$ lspci -nn | grep -i smartnic5e:00.0 Ethernet controller [0200]: ... [...]
# CXL.cache 자체는 sysfs에 노출 안 됨$ ls /sys/bus/cxl/devices/# (Type 1만 있으면 빈 디렉토리)
# vendor 드라이버 내부에서 cache 기능 사용$ dmesg | grep -i "cxl.cache"nic0: CXL.cache enabled, cache size 8 MBType 2의 CXL.cache는 coro·CUDA 같은 high-level runtime이 bias·access pattern hint를 제공.
#자주 하는 실수
#”CXL.cache가 있으면 무조건 빠르다”
Cache hit rate가 충분해야 합니다. 불규칙한 access pattern은 cache miss → DMA-like round-trip. 워크로드 temporal locality 분석 필수.
#”Cache line padding은 불필요하다”
CXL.cache 환경에서는 false sharing이 매우 비쌉니다. modern C++의 std::hardware_destructive_interference_size 사용 권장.
#”Device cache state는 software가 관리”
Hardware가 자동 관리합니다. software는 bias hint·prefetch 같은 hint만 줄 수 있고 state transition은 hardware가 결정.
#”MESI면 모든 CXL 디바이스가 호환”
State set이 디바이스마다 다를 수 있음. MESI·MOESI·MESIF 변형들. capability 확인 필요. CXL.io DVSEC에서 지원 state 표기.
#”Snoop overhead가 항상 무시 가능”
High-contention shared data에서는 snoop 트래픽이 dominant가 됩니다. Type 2 GPU의 shared weight scan에서 snoop 비용이 compute보다 큰 워크로드도 존재.
#정리
- CXL.cache는 디바이스가 host memory를 native cache하는 프로토콜입니다.
- D2H·H2D 메시지가 MESI coherency를 양방향 유지. PCIe DMA보다 정교한 메시지 set.
- Read는 RdShared/RdOwn, Write는 RdOwn → Modified, Host의 update는 Snoop으로 device cache invalidate.
- Type 1 SmartNIC의 packet metadata 캐싱이 가장 명확한 production fit.
- False sharing이 최악 시나리오 — cache line padding으로 회피.
#다음 편
Ch 8: CXL.mem — M2S·S2M·HDM Decoder에서 host가 device memory에 load/store하는 CXL.mem 프로토콜의 메시지 흐름과 HDM Decoder의 주소 매핑을 본격적으로 분해합니다.
#관련 항목
- Ch 3: 메모리 일관성 모델
- Ch 6: CXL.io
- Ch 8: CXL.mem
- Embedded Performance Engineering Ch 38: Cache Coherency 프로토콜
#시리즈 자료 출처 안내
본 글은 CXL Consortium·Linux drivers/cxl/ 소스·academic 연구를 1차 자료로 합니다. CXL 4.0 Specification은 § navigation aid로만 인용. 자세한 spec 인용 정책은 Ch 1 footer 참고.
CXL 4.0 Internals · 7 of 15
- 1Ch 1: CXL의 자리와 진화 — 1.1에서 4.0까지
- 2Ch 2: System Architecture — Type 1·2·3·MLD·MH-MLD
- 3Ch 3: 메모리 일관성 모델 — HDM-DB·HDM-D·Bias·BISnp
- 4Ch 4: Pooling·GFAM·Fabric — Multi-host 메모리 공유
- 5Ch 5: CXL 4.0의 핵심 새 기능 — 128 GT/s·Bundled Port
- 6Ch 6: CXL.io — PCIe와의 차이·DOE·DVSEC
- 7Ch 7: CXL.cache — D2H·H2D 흐름과 coherency state
- 8Ch 8: CXL.mem — M2S·S2M·HDM Decoder
- 9Ch 9: Flit Format — 68B vs 256B vs Latency-Optimized
- 10Ch 10: ARB/MUX — 세 프로토콜의 PHY 다중화
- 11Ch 11: Linux drivers/cxl/ 분석 — Mainline kernel CXL 구현
- 12Ch 12: QEMU CXL 에뮬레이션 — 노트북에서 CXL 개발
- 13Ch 13: Switching·Fabric Manager — 2.0 pooling에서 3.x fabric까지
- 14Ch 14: Security — IDE·SPDM·TSP·CXL TEE
- 15Ch 15: RAS·Performance·Compliance — 운용·검증의 마지막 단계