Codex 자동 연구로 커널을 232배 빠르게 만든 방법
Codex에게 코드를 한 번 잘 짜게 하는 대신, 스스로 실험을 반복하게 만들어 GPU 연산을 232배 개선한 사례
GPU Mode의
qr_v2최적화 대회에서 183명 중 12위시작 성능은 약 419ms
최종 성능은 1.805ms
약 14일 동안 1,500회 이상 submission을 반복
핵심은 좋은 프롬프트 하나가 아니라, AI가 다음 과정을 계속 반복할 수 있는 환경을 만드는 것이었음
코드 수정
실행
정확성 검증
성능 측정
결과 기록
다음 가설 수립
다시 실험
Auto-Research는 쉽게 말하면 “AI에게 R&D 루프 자체를 맡기는 방식”
일반적인 Coding Agent 사용은 대체로
요구사항 전달 → 코드 생성 → 사람이 확인
Auto-Research는 여기서 한 단계 더 나아가
목표 설정 → 실험 → 측정 → 실패 원인 분석 → 다음 시도
까지를 에이전트가 반복
특히 성능 최적화처럼 결과를 숫자로 바로 판정할 수 있는 문제와 잘 맞음
“이 코드가 더 좋은가?”를 사람이 감으로 판단하지 않아도 benchmark가 명확한 답을 주기 때문
GPU 문제였지만, 핵심 아이디어는 일반적인 백엔드 성능 튜닝과 크게 다르지 않음
처음 구현은 이미 존재하는 라이브러리 호출을 많이 사용했지만 충분히 빠르지 않았음
프로파일링을 통해 실제 병목을 찾고
작은 연산을 여러 번 호출하는 방식 대신
GPU가 효율적으로 처리할 수 있는 큰 연산 단위로 재구성
백엔드 관점으로 비유하면
DB query를 수천 번 날리는 코드를 batch query로 변경하거나
작은 RPC를 반복 호출하는 대신 한 번의 bulk request로 묶는 것과 비슷함
즉 “연산 자체를 조금 빠르게”보다 “일하는 구조 자체를 바꾸는 것”이 큰 개선을 만들었음
GPU 최적화에서 발견한 대표적인 구조적 개선
QR decomposition이라는 수치 계산에는 앞 단계 결과를 기다려야 하는 순차 작업이 존재
순차 작업이 많으면 GPU의 대규모 병렬 연산 장점을 충분히 활용하기 어려움
이를 여러 작업으로 묶어 한꺼번에 처리하도록 알고리즘을 변경
결과적으로 GPU가 잘하는 큰 행렬 연산(GEMM) 비중을 높임
세부 알고리즘을 모르더라도 핵심은 단순함
작은 작업을 많이 수행하지 말고
하드웨어가 가장 잘 처리하는 형태로 문제를 재구성한다
처음부터 복잡한 AI Agent Framework를 만든 것은 아님
실험 환경의 핵심은 몇 개의 문서와 로그 파일이었음
problem_statement.md해결해야 할 문제와 제한조건
AGENTS.md에이전트가 따라야 하는 작업 규칙
log.md어떤 실험을 했고 성공했는지 실패했는지 기록
여기서 특히 중요한 것은 로그
이전 실험 결과를 남기지 않으면 새로운 agent session이
이미 실패한 아이디어를 다시 시도하거나
이전에 어떤 변경이 효과가 있었는지 잊어버리는 문제가 발생
결국 Auto-Research에서는 코드만큼 실험 기록이 중요
“최적화해줘”보다 숫자로 판정 가능한 목표를 줌
Codex의
/goal을 활용해 목표에 도달할 때까지 반복하도록 구성목표는 최대한
구체적이고
측정 가능하며
성공 여부가 명확하도록 설정
예를 들면
“현재
n=512최고 기록보다 빠르게 만들어라”“기존 라이브러리는 fallback으로만 사용하라”
같은 형태
일반적인 개발에서도
“API를 빠르게 만들어라”보다
“p99 latency를 250ms에서 150ms 이하로 줄여라”
같은 목표가 Agent에게 훨씬 유리함
Agent가 작업 중일 때도 계속 방향을 확인
/btw,/side등을 사용해 main loop를 중단하지 않고 상태를 질문예를 들어
현재 가장 큰 병목은 무엇인가?
최근 가장 효과가 있었던 변경은?
지금 시도하고 있는 가설은?
다음 후보는?
이런 질문을 통해 AI에게 직접 코드를 지시하기보다 연구 방향을 관리
초반에는 AI에게 맡기는 것만으로도 큰 개선이 나왔지만, 성능이 좋아질수록 문제가 달라짐
처음에는 명확한 비효율이 많기 때문에 Agent가 쉽게 개선
하지만 일정 수준을 넘어서면 작은 parameter 조정만 반복하는 현상이 발생
약
3ms수준에 도달한 이후 이런 local maximum 문제가 눈에 띄게 증가이 단계부터는
profiling 결과 확인
새로운 알고리즘 방향 제안
다른 모델에게 아이디어 요청
실험 방향 변경
같은 사람의 개입이 효과적이었음
중요한 것은 매번 코드를 직접 고치는 게 아니라 Agent가 같은 방향에서 맴돌 때 탐색 방향을 바꿔주는 것
현재 최고 코드 하나만 계속 개선하면 좋은 아이디어를 너무 빨리 버리게 됨
초반에는 항상
현재 최고 코드
새로운 코드
둘을 비교해 빠른 쪽만 남기는 방식으로 진행
문제는 구조적으로 큰 변경은 처음부터 최고 성능이 나오기 어렵다는 것
가능성이 있는 새 아이디어라도 첫 benchmark가 조금 느리면 바로 사라짐
그래서 하나의 Best 대신 여러 후보를 동시에 유지하는
Beam of Candidates방식으로 변경서로 다른 방향의 구현을 3~5개 정도 동시에 유지
예를 들면
Exploit
현재 최고 구현을 조금 더 개선하는 방향
Near-miss
거의 좋은 결과가 나왔지만 아직 최고를 넘지 못한 방향
High-risk
알고리즘 자체를 크게 바꾸는 실험적인 방향
머신러닝의 Beam Search처럼 당장 1등이 아니더라도 가능성 있는 후보를 살려두는 방식
일반적인 소프트웨어 개발에서도 활용 가능
캐시 최적화 버전
DB query 변경 버전
비동기 처리 버전
등을 동시에 실험하고 나중에 조합할 수 있음
서로 다른 아이디어를 조합했을 때 갑자기 성능이 좋아질 수도 있음
A 변경만 적용하면 별 차이가 없고
B 변경만 적용해도 별 차이가 없지만
A+B를 같이 적용하면 큰 개선이 생기는 경우가 있음
따라서 단일 실험 결과만 보고 아이디어 전체를 폐기하지 않음
“왜 느린가”라는 근거가 확인됐을 때 후보를 버리는 것이 중요
Profiling이 없으면 AI도 추측으로 최적화하게 됨
성능이 느린 이유를 실제 데이터로 확인
특히 큰 개선 이후에는 profiling을 다시 수행
이전에는 A가 병목이었더라도 A를 개선하고 나면 B가 새로운 병목이 되기 때문
이는 일반 서비스 성능 튜닝에서도 동일
CPU를 줄였더니 DB가 병목이 되고
DB를 개선했더니 network latency가 병목이 되는 식
최신 코드에 대한 최신 profile을 기준으로 판단해야 함
Implementation Hints
사용한 디렉토리 구조
qr/
├── submission.py # the live entry
├── submission_*.py (560) # named submission variants (crystal_rain, blue_reply, …)
├── modal_b200_*.py (119) # Modal B200 probe / compare scripts
│
├── AGENTS.md # top-level notes / logs
├── attempts_log.md
├── claude_ideas.md
├── leaps.md
├── problem_statement.md
│
├── docs/ ( 68) # per-experiment writeups & status docs
├── code/ # the actual QR kernel source tree
├── scripts/ # summarizers, timing, submit helpers
├── archive/ # cleaned-out old submissions & probes
│ ├── submissions_20260616_17/
│ ├── submissions_20260618_20/
│ ├── probe_scripts_cleanup_20260627/
│ └── …
├── submit_logs/ # logs provided by the evaluator for each submission
└── profile.*/ # captured NCU profile runs최종 AGENTS.md:
리더보드 Agent 메모
이 workspace는 리더보드형 최적화 작업용이며, 사용자가 명시적으로 덮어쓰지 않는 한 아래 상시 지침을 따름
제출 규율
필요한 경우 sub-agent를 적극적으로 사용하고 충분한 context를 제공할 것
큰 변경이나 큰 성능 개선이 있었다면 profiling을 다시 수행할 것
같은 방향에서 계속 막히면 더 강한 모델을 advisor로 사용해 다른 관점을 얻을 것
구현이 어렵다는 이유만으로 가능성 있는 아이디어를 피하지 말 것
위험을 감수하는 실험을 주저하지 말 것
새로운 아이디어를 받아들이고 때때로 인터넷을 검색해 탐색 범위를 넓힐 것
제출 전 후보 파일에 사용할 수 있는 가장 저렴한 sanity check를 실행할 것
제출 log는
submit_logs/아래에 보관할 것제출 출력은 항상 timestamp가 붙은 log로 저장할 것
리더보드 제출 간격을 두고, 명시적 요청이 없으면 연속 제출을 쌓지 말 것
timeout은 결론 미정으로 취급하고 correctness·performance 실패로 판정하지 말 것
완료된 residual failure나 timing regression은 실제 증거로 볼 것
완료된 pass·fail·timing 출력만 증거로 인정할 것
Beam Search 규율
단일 최고 후보만 계속 수정하는 hill climb하지 말고, 일부 부정적 결과로 유용한 요소가 조기에 폐기되지 않도록 작은 active idea beam을 유지할 것
docs/에 최신 beam 메모를 둘 것각 beam에 parent candidate, hypothesis, 정확히 바꾼 function·gate, 현재 최고 candidate·log, 다음 singleton·조합·폐기 결정을 기록할 것
작업이 충분하면 active beam을 최소 3개 유지할 것
현재 최고 후보에 가까운 exploit beam 1개
near-miss beam 1개
profiling이나 외부 아이디어에서 나온 구조적·고위험 beam 1개
전체 탐색을 잠식하지 않은 경우에만 cleanup·compile-time beam 1개
명시적으로 병렬 sweep을 요청하지 않았다면 sub-agent에는 같은 작은 parameter 변형이 아니라 서로 다른 beam을 맡길 것
고립된 singleton 실패만으로 idea family의 종료를 선언하지 말 것
두 아이디어가 각각 중립적이거나 약간 느리더라도 서로 독립적인 비용을 건드린다면 correctness 위험이 크지 않은 한 결합한 뒤 폐기할 것
반복 가능한 부분 승리, 중요 case 개선, overhead 제거, 다른 beam과 결합 가능한 알고리즘 변경이 있으면 near-miss를 beam 재료로 보존할 것
본질적 correctness failure, 합리적 retune 뒤의 반복적 유의미한 regression, singleton과 가능한 조합의 동반 실패, 대상 비용이 더는 중요하지 않다는 profile 증거, 더 가치 있는 beam을 막는 구현 비용이 있을 때만 명확한 사유와 함께 beam을 종료할 것
제출 3~5회마다 현재 beam 순위와 다음 조합 후보를 beam 메모에 갱신할 것
Promotion / Git 관리
새 후보를 active file로 승격할 때 promoted candidate, active file, 증거 문서·log, archive 이동 내역을 stage할 것
사용자가 금지하지 않았다면 promotion 뒤 commit할 것
commit 제목은 소문자로 쓰고 본문에는 변경 사항과 개선을 만든 요인을 모두 적을 것
Profiling / 증거 관리
오래된 sidecar timing보다 현재 active evidence를 우선할 것
원시 profile log와 JSON은
submit_logs/에 보관할 것후보가 거절되거나 승격되면
docs/의 관련 문서를 갱신할 것검색에는 가능하면
rg를 사용할 것root를 탐색하기 쉽도록 오래된 candidate·profile log·probe script를 archive할 것
이미 시도한 아이디어
모든 시도 요약을 여기에 복제하지 말고, 반복 전에
docs/를 확인하며 아이디어가 거절되거나 승격되면 관련 문서를 갱신할 것거절된 아이디어를 그대로 반복하지 말고, 다시 시도한다면 알고리즘 차이를 문서·log에 명시할 것
platform이나 evaluator 규칙이 특정 아이디어 부류를 거절하면 미래 agent가 같은 무효 경로를 재발견하지 않도록 분명히 기록할 것
실험을 끝내고 개선할 수 있었던 부분
입력 데이터의 특성을 더 적극적으로 활용할 수 있었음
기존 GPU 라이브러리에 덜 의존하고 custom kernel을 더 많이 구현할 수 있었음
mixed precision 등 GPU 수치 연산 특성을 더 일찍 이해했다면 추가 개선 가능성이 있었음
Beam of Candidates를 프로젝트 초반부터 적용했으면 탐색 효율이 더 좋았을 가능성이 높음
필요한 profiling 도구도 더 일찍 구축했으면 좋았음
최신 GPU가 제공하는 일부 저수준 명령도 충분히 활용하지 못함
결국 도메인 지식이 부족하면 AI도 질문하지 못하는 영역이 존재
결론
최종적으로 183명 중 12위, baseline 대비 232배 성능 향상을 달성
하지만 더 중요한 결과는 특정 GPU 코드를 빠르게 만든 것보다 Auto-Research loop를 실제로 어떻게 운영해야 하는지 확인했다는 점
도메인 전문성은 여전히 중요
어떤 측정을 해야 하는지 알 수 있고
좋은 실험 환경을 설계할 수 있으며
Agent가 잘못된 방향으로 갈 때 올바르게 steering할 수 있음
Auto-Research 시스템에는 크게 두 가지 방향이 존재
어떤 문제든 해결하는 범용 연구 Agent
특정 문제와 실행 환경에 최적화된 전용 연구 Agent
이번 경험에서는 특정 문제를 잘 측정하고 검증할 수 있도록 만든 전용 harness가 더 효과적이었음
source https://sankalp.bearblog.dev/autoresearch/
HN에서는 232배라는 수치 자체보다, 자동 최적화가 통하는 조건에 더 주목했다. 성능 측정, 프로파일링, 정답 검증이 반복 과정마다 명확한 신호를 주는 문제라면 LLM이 스스로 수정하며 빠르게 개선할 수 있다는 평가가 중심을 이뤘다. GPU 커널과 SIMD처럼 목표를 수치로 비교하고 실패를 즉시 판정할 수 있는 영역이 특히 잘 맞는다는 것이다.
실무 경험도 이를 뒷받침했다. 영상 코덱의 SSE·AVX 구현, NEON 커널, Rust 기반 연산 엔진, 오래된 게임의 역공학 등에서 기준 구현과 테스트를 고정해 두자 반복 작업의 속도가 크게 높아졌다는 사례가 이어졌다. 경로 단위 테스트와 기준값 비교, 대표 입력을 이용한 종단 간 벤치마크, 프로파일 결과를 함께 제공하면 성능 개선 중 정확성이 흔들리는 문제를 줄일 수 있다는 조언도 나왔다. 반대로 화면처럼 성공 여부를 모델이 정확히 판단하기 어려운 작업에서는 완료되지 않은 결과를 성공으로 오인하기 쉽다는 지적이 있었다.
가장 큰 경계선은 대회 점수와 범용 소프트웨어 사이에 놓였다. 상위권 해법 다수가 대회에 없던 입력 크기에서 실패했다는 증언은 극단적인 최적화가 입력 조건에 과도하게 맞춰질 수 있음을 보여준다. 특정 모델 크기를 고정해 운영하는 환경이라면 이런 특화가 장점이지만, 다양한 입력을 받아야 하는 오픈소스 라이브러리에서는 수치 안정성, 가독성, 유지보수 비용이 더 중요하다. 전문가가 도메인 지식으로 탐색 범위를 좁히고 불필요하게 커진 코드를 다시 정리해야 한다는 경험도 공유됐다.
결국 도입 여부는 LLM의 코딩 능력보다 검증 장치의 품질로 판단해야 한다. 허용할 입력 범위와 오차, 기준 구현, 회귀 테스트를 먼저 정하고 범위 밖 입력까지 시험해야 한다. 빠른 특화가 목표인지, 변화하는 조건에서도 신뢰할 수 있는 구현이 목표인지도 분명히 해야 한다. 이 구분이 없으면 높은 벤치마크 점수가 실제 운영 가치나 유지 가능한 코드로 이어진다고 보기 어렵다.
