강화학습은 평균 속도로 굴러가지 않습니다. 병렬로 뿌린 rollout 중 가장 느린 애가 한 스텝을 끝내는 시간을 정합니다. AWS가 10월 9일 Compute 블로그에 공개한 보고서는 이 당연한 말을 숫자로 증명합니다. Firecracker microVM으로 강화학습 샌드박스를 빽빽하게 채우면, 평균(p50)은 그대로인데 꼬리(p99)가 폭발한다는 것. 500개가 넘는 설정에서 10만 건이 넘는 샘플을 쟀고, vCPU당 microVM 1개를 넘는 순간 p99가 치솟았습니다.
실험 장치: 맨 위에서 재는 게 아니다
배경부터 정리합니다. 검증 가능한 보상으로 학습하는 RLVR 방식은 수천 개의 격리 샌드박스를 병렬로 돌려야 합니다. 빨리 돌리고 빨리 회수할수록 시간당 스텝이 늘고, 스텝당 비용이 줍니다. AWS 팀이 올린 기준 구조는 이렇습니다.
EC2 metal 호스트 + 호스트 에이전트(DaemonSet)
- CPU 토폴로지 탐색, microVM마다 cgroup
- Firecracker jailer 생명주기, CPU 피닝, NUMA 배치
- 미리 부팅해둔 warm pool에서 디스패치 + 텔레메트리
- 위에는 K8s 클러스터
측정은 m8i·m8a·m8g metal-48xl 계열에서 했고, 공개된 수치는 m8i·m8a 중심입니다. 전제는 분명합니다. 커널 6.2 이상(cgroup 격리 모드), Firecracker 1.7 이상과 jailer, labsweep 빌드용 Go 1.22 이상. CPU·메모리 배치만 봤고, 스토리지(EBS·로컬 SSD)와 LLM 엔드포인트 네트워크는 고정했습니다. 한 번 정한 밀도를 유지한 채 재는 방식이라, 동적 churn은 범위 밖입니다.
밀도를 조절하는 손잡이는 표로 보면 한눈에 들어옵니다.
코어 피닝 (cpuset.cpus) → 물리 코어 전용, 스케줄러 꼬리 제거
NUMA 묶기 (cpuset.mems) → 할당을 로컬에, 거리 행렬 확인
SMT on/off → m8i만 해당 (m8a·m8g는 SMT 없음)
L3 캐시 도메인 피닝 → 작업 집합이 microVM당 4MiB 넘으면 효과
cgroup 격리 파티션 → 워크큐 간섭 제거
게스트 메모리 크기 → M 계열은 vCPU당 4GiB가 기준
글에 나온 예시 그대로 옮기면 감이 옵니다.
mkdir -p /sys/fs/cgroup/microvm/vm-012
echo "12" > /sys/fs/cgroup/microvm/vm-012/cpuset.cpus
echo "0" > /sys/fs/cgroup/microvm/vm-012/cpuset.mems
firecracker-jailer --id vm-012 \
--exec-file /usr/bin/firecracker \
--parent-cgroup microvm/vm-012 \
--uid 1000 --gid 1000
재현용 도구 labsweep(Go제 하네스)의 일도 정해져 있습니다. sysfs에서 토폴로지를 읽고, 설정×밀도 행렬을 짜고, 각 밀도에서 jailer로 묶은 Firecracker를 정해진 동시성으로 띄운 뒤, 모든 게스트에서 워크로드를 동시에 돌려 microVM별 지연을 기록합니다. 날것 샘플과 백분위 집계, 분산, 출처(인스턴스·CPU·커널·Firecracker 버전)까지 내놓고, 실패 샘플은 숨기지 않고 보고합니다. m8a에서의 전형적인 실행은 이런 모양입니다.
labsweep -configs A,B \
-densities 90,120,150,186 \
-repeats 5 \
-resident-kib 131072 \
-steps 14 \
-write-kib 4096
돌린 워크로드는 네 가지입니다. 짧은 검증(테스트 스위트), 빌드 위주(컴파일·링크), 14턴짜리 실제 RL 에피소드 재생, 그리고 대조군인 합성 연산 루프. 이 구분이 뒤에서 중요해집니다.
1.0의 벽: vCPU당 1개를 넘기면 벌어지는 일
핵심 결과는 이식성이 좋습니다. 절대 개수가 아니라 비율로 표현됩니다. vCPU당 microVM 1.0까지는 꼬리가 납작하다가, 그 다음 15% 밀도 구간에서 p99가 치솟아 새 고원에 안착합니다. 중앙값은 그대로입니다. 부록 표(m8i, SMT off, 물리 코어 96, 고정 안 한 설정 A)를 옮겨봅니다.
밀도 비율 p50 p99 그룹 증폭(G=8 / 16 / 64)
45 0.47x 7,768us 7,857us 1.01 / 1.01 / 1.01
90 0.94x 7,740us 8,035us 1.01 / 1.01 / 1.04
100 1.04x 7,740us 8,601us 1.01 / 1.03 / 1.13
110 1.15x 7,737us 9,909us 1.01 / 1.04 / 1.32
135 1.44x 7,743us 15,601us 1.03 / 1.20 / 2.01
186 1.94x 7,744us 15,697us 1.22 / 1.56 / 2.03
p50은 7.7ms에서 꼼짝 않고, p99는 1.04배 밀도에서 +7%, 1.15배에서 +23%, 1.44배부터 약 2배입니다. 오른쪽 증폭 칸이 진짜 함정입니다. GRPO처럼 그룹의 가장 느린 애를 기다리는 방식에서는, 그룹이 커질수록 p99 사건을 밟을 확률이 올라갑니다. G=64면 단계의 47%近く에서 p99를 만납니다. 중앙값 대시보드는 이걸 숨깁니다. 봐야 할 건 증폭 계수입니다. AI 모델 속도·지연 가이드에서 평균과 꼬리를 함께 보라고 한 이유가 여기 있습니다.
피닝은 진짜 workload에서만 통한다
두 번째 결과는 "측정용 장난감과 진짜 샌드박스는 다르다"는 교훈입니다. 합성 연산 루프에서는 코어 피닝을 해도 같은 밀도에서 차이가 거의 없었습니다. 그런데 진짜 샌드박스에서는 p99/p50이 1.1배 근처로 조여졌고, 밀도가 올라갈수록 이득이 커졌습니다.
SMT도 workload 따라 갈립니다. 파일·프로세스 포크·git 대기가 섞인 I/O 바운드(대부분의 RL 샌드박스가 여기)에서는 SMT on이 이깁니다. 같은 m8i 호스트에서 검증 1.14배, 빌드 1.13배, RL 에피소드 재생 1.17배의 처리량이 났고, 고밀도에서는 vCPU 수가 1.0 기준을 넘기 때문에 1.49배까지 벌어졌습니다. 반대로 연산 바운드 루프에서는 SMT off가 꼬리 분산이 촘촘하고 예측 가능했습니다. 1.0 이하에서는 SMT off가 작업당 살짝 낫습니다. 만능 정답은 없고, 목표 밀도에서 재는 수밖에 없습니다.
마지막으로 메모리 벽. M 계열은 vCPU당 4GiB라서, 테스트한 workload는 전부 vCPU를 먼저 다 썼습니다. vCPU당 메모리가 더 필요하면 메모리 최적화 패밀리로 옮겨야 하고, 그럼 호스트당 vCPU가 줄면서 최대 밀도도 낮아집니다. 스펙 시트가 아니라 자기 workload로 튜닝하라는 AWS의 당부가 이 대목과 맞닿아 있습니다. 인스턴스마다 SMT·캐시·NUMA가 다르니까요.
CodeBridge Mini Lab: p50·p99·실패율을 함께 재기
브리핑의 실무 액션을 실험 순서로 바꿨습니다. 샌드박스 동시 실행 수를 올리면서 세 개를 같이 봅니다.
① 밀도를 비율로 환산:
- 호스트 vCPU 수 확인 (SMT on/off에 따라 분모가 바뀜)
- 0.5x → 0.94x → 1.04x → 1.15x → 1.44x → 1.9x 순으로 쓸기
② 매 밀도에서 5회 이상 반복:
- p50, p99, p99/p50, 그룹 증폭 max(group)/p50 (G=8/16/64 중 자기 값)
- 실패 샘플은 버리지 말고 따로 집계
- EBS·LLM 엔드포인트·버전 출처는 고정·기록
③ 판정선:
- p50은 납작한데 p99/p50 > 1.2 또는 G=64 증폭 > 1.1이면 벽을 넘은 것
- 한 칸 뒤로 물러나 증폭이 납작한 가장 높은 밀도에 고정
- 진짜 workload로 잴 것 (합성 루프는 피닝 효과를 숨김)
warm pool은 별개 손잡이입니다. 디스패치 지연을 다스리는 장치라서, 밀도 스위프와 섞지 말고 따로 보세요. 정리할 때는 CDK destroy, metal 종료, S3 rootfs와 CloudWatch 로그 그룹 삭제까지 한 세트로 묶어두는 게 좋습니다.
결론: 평균이 아니라 가장 느린 애를 본다
한 줄로 정리합니다.
병렬 학습의 속도는 평균이 아니라 꼬리가 정한다.
vCPU당 1.0의 벽, 합성 루프를 속이는 피닝, workload 따라 뒤집히는 SMT, vCPU를 먼저 다 쓰는 메모리 구조. 전부 같은 말을 합니다. 여유처럼 보이는 초과 배치는 꼬리가 학습 시간을 지배하기 전까지만 여유입니다. 오늘 자기 샌드박스의 동시 실행 수를 비율로 바꿔보세요. 1.0을 넘겼는데 p99를 안 보고 있다면, 가장 느린 작업 하나가 매 스텝 돈을 쓰고 있을 겁니다. 에이전트 샌드박스 보안 가이드의 격리 원칙과 AI 옵저버빌리티 글의 계측 관점을 옆에 두면, 이 실험을 운영 지표로 이을 수 있습니다.
함께 읽으면 좋은 글
참고 자료
- AWS Compute Blog: Scaling RL rollouts with Firecracker on Amazon EC2 metal
- Firecracker Docs: Getting started
- AWS Docs: EC2 bare metal instance types
이 주제를 직접 따라가며 배우고 싶다면
격리된 실행 환경에서 AI가 일하게 하고, 권한과 검증으로 통제하는 흐름이 이 글의 샌드박스 운영과 바로 이어집니다. 감으로 쓰는 AI 코딩에서 벗어나 검증 있는 개발 흐름을 만들고 싶다면 이 과정부터 보세요.