연구 중심 에이전트: 코딩 전 논문을 읽을 때
코드만 분석하던 기존 AI 에이전트에 '논문 및 경쟁 프로젝트 리서치' 단계를 추가했더니, 사람이 놓칠 수 있는 핵심 최적화(OOM 문제 해결 등)를 찾아냅니다. 실제로 llama.cpp 프로젝트에 적용해 약 3시간 만에 x86 환경에서 15%, ARM에서 5%의 속도 향상을 달성하며 그 성능을 입증했습니다. 이는 단순한 코딩 도구를 넘어, 도메인 지식을 활용하는 시니어 엔지니어처럼 동작하는 에이전트의 가능성을 보여줍니다.
목차
- 코드 컨텍스트만으로 작동하는 경우
- 코드 컨텍스트만으로 한계에 부딪히는 경우
- 리서치 단계 추가
- 실험 로그
- 리서치 결과
- 전환: 연산(Compute)에서 메모리(Memory)로
- 성공한 최적화들
- 소프트맥스 퓨전 (Softmax fusion)
- RMS 정규화 퓨전 (RMS norm fusion)
- 적응형 from_float 병렬화 (Adaptive from_float parallelization)
- 그래프 수준 RMS_NORM + MUL 퓨전 (Graph-level RMS_NORM + MUL fusion)
- 플래시 어텐션 KQ 퓨전 (Flash attention KQ fusion)
- 결과
- 작동하지 않았던 것들
- 실패한 실험들
- 벤치마크 버그
- 클라우드 VM의 노이즈
- 코드 리뷰
- 코딩 에이전트를 위한 시사점
- 여러분의 프로젝트에 직접 적용해보기
TL;DR (요약): 코딩 에이전트는 코드를 작성하기 전에 논문을 읽고 경쟁 프로젝트를 학습할 때 더 나은 최적화를 생성합니다. 우리는 autoresearch / pi-autoresearch 루프에 문헌 검색 단계를 추가하고, 4개의 클라우드 VM을 사용해 llama.cpp를 대상으로 실행했습니다. 그 결과 약 3시간 만에 5가지 최적화를 도출하여 x86에서 플래시 어텐션 텍스트 생성 속도를 +15%, ARM(TinyLlama 1.1B)에서 +5% 향상시켰습니다. 전체 설정은 벤치마크와 테스트 스위트가 있는 모든 프로젝트에서 작동합니다.
핵심 요약:
- 코드를 작성하기 전에 논문과 경쟁 프로젝트를 학습하는 에이전트는 코드만 다루는 에이전트가 놓치는 최적화를 찾아냅니다.
- 문헌 연구는 CUDA/Metal 백엔드에는 있지만 CPU에는 없는 연산자 퓨전(operator fusion)을 에이전트가 파악하게 해주었습니다.
- 30개 이상의 실험 중 5개가 성공했습니다: 4개의 커널 퓨전(kernel fusion)과 1개의 적응형 병렬화.
- 가장 큰 성과는 플래시 어텐션의 QK 타일에 대한 3번의 패스를 단일 AVX2 FMA 루프로 퓨전한 것입니다.
- arXiv를 검색하는 것보다 프로젝트 포크(fork)와 다른 백엔드를 연구하는 것이 더 생산적이었습니다. ik_llama.cpp와 CUDA 백엔드는 최종 5가지 최적화 중 2개에 직접적인 영감을 주었습니다.
- 총 비용: 약 $29 (CPU VM $20, API 호출 $9) / 4개의 VM으로 약 3시간 소요.
코드 컨텍스트만으로 작동하는 경우
Karpathy의 autoresearch는 코딩 에이전트가 자율적으로 신경망 학습 스크립트를 개선할 수 있음을 보여주었습니다. 우리의 이전 글에서는 이를 16개의 GPU로 확장하여 8시간 동안 약 910개의 실험을 실행하도록 관찰했고, val_bpb를 2.87% 감소시켰습니다. 이 에이전트는 코드 컨텍스트만으로 아이디어를 냈으며, 모든 실험은 동일한 train.py에 대한 변형이었습니다. 그 이후로 pi-autoresearch는 이 루프를 벤치마크 가능한 모든 대상에 사용할 수 있는 재사용 가능한 확장으로 일반화했습니다.
Shopify CEO인 Tobi Lütke는 연간 $292B의 상품 거래량을 처리하는 Ruby 템플릿 엔진인 Liquid에서 이를 실행했습니다. 에이전트는 약 120개의 실험을 실행하여 93개의 커밋을 생성했고, 974개의 단위 테스트에서 회귀(regression) 없이 파싱 및 렌더링 시간을 53%, 할당을 61% 줄였습니다 (Simon Willison의 글, Tobi의 글). 이 경우 최적화 대상이 소스 코드상에 보였습니다. Liquid 에이전트는 토크나이저를 읽고 StringScanner가 병목 현상임을 파악한 다음, 코드베이스만으로 대안을 브레인스토밍할 수 있었습니다.
코드 컨텍스트만으로 한계에 부딪히는 경우
모든 최적화 문제가 이런 식으로 작동하는 것은 아닙니다. 코드베이스는 코드가 무엇을 하는지는 알려주지만, 왜 느린지 또는 이 코드베이스 밖에 어떤 대안이 있는지는 알려주지 않습니다. (예를 들어, 시니어 엔지니어가 가지고 있을 도메인 지식인 arXiv 논문이나 경쟁 프로젝트에 답이 있는 경우) 소스 코드만으로 작업하는 에이전트는 얕은 수준의 가설만 세우게 됩니다.
우리는 에이전트를 llama.cpp의 CPU 추론 경로로 향하게 했을 때 이 문제를 보았습니다. 최적화 탐색 공간은 '다른 학습률(learning rate)을 시도해보라'가 아닙니다. '이 두 메모리 패스를 퓨전해야 하는가?', '이 워크로드가 연산 집중적인가(Compute-bound) 아니면 메모리 집중적인가(Memory-bound)?', 'ik_llama.cpp는 이미 무엇을 시도했는가?'와 같은 질문들입니다.
에이전트의 첫 번째 실험 웨이브(wave)는 문제를 보여주었습니다. 코드 컨텍스트만으로 작업한 결과, GGML의 행렬 곱셈 핫 패스에 있는 양자화된 닷 프로덕트 내의 SIMD 마이크로 최적화로 바로 직행했습니다. 다음을 시도했습니다:
- Q4_0 닷 프로덕트 이너 루프에서의 AVX2 프리페칭 (+0.8%)
- 듀얼 누산기(dual accumulators)를 사용한 2x 루프 언롤링 (+0.9%)
- mul_mat의 임시 버퍼 제거 (-2.8%, 성능 회귀 발생)
- 블록 경계 계산 외부로 추출(Hoisting) (+0.6%)
이 모든 것은 노이즈 오차 범위 내에 불과했습니다. 에이전트의 사후 분석(postmortem) 결과는 다음과 같습니다: "웨이브 1 결과는..."