100B 벡터 검색을 200ms에? Turbopuffer ANN v3 아키텍처 딥다이브
솔직히 말해서, 요즘 쏟아져 나오는 ‘Vector DB’ 관련 글들에 좀 지쳐있었습니다. 대부분이 HNSW 알고리즘 래퍼(wrapper) 수준이거나, “우리 것이 더 빠르다”는 벤치마크 전쟁뿐이었으니까요.
그런데 최근 Turbopuffer 팀이 공개한 ANN v3 포스트는 오랜만에 엔지니어의 심장을 뛰게 만들었습니다. 단순히 “빠르다”가 아니라, 하드웨어의 한계(Memory Hierarchy)를 밑바닥부터 긁어서 최적화한 진짜 시스템 엔지니어링 이야기이기 때문입니다.
1,000억(100B) 개의 벡터. 데이터 크기만 200TiB입니다. 이걸 200ms 안에, 그것도 p99 latency로 처리한다? 이건 단순히 알고리즘을 잘 짠다고 되는 문제가 아닙니다. 오늘은 이들이 어떻게 ‘Mechanical Sympathy(하드웨어 공감)‘를 통해 이 말도 안 되는 스케일을 정복했는지 뜯어보겠습니다.
1. 벡터 검색의 진짜 병목: Bandwidth vs Compute
대용량 처리를 해보신 분들은 아시겠지만, 시스템의 병목은 크게 두 가지로 나뉩니다. CPU가 느려서 못 따라가는 Compute-bound, 혹은 데이터를 CPU로 퍼 나르는 속도가 느린 Bandwidth-bound.
보통 벡터 검색(Vector Search)은 Bandwidth-bound 입니다. 내적(Dot Product) 연산 자체는 단순한데, 수억 개의 벡터 데이터를 메모리에서 레지스터로 가져오는 비용이 훨씬 크기 때문이죠. 이걸 ‘Arithmetic Intensity(연산 강도)‘가 낮다고 표현합니다.
Turbopuffer 팀은 이 병목을 해결하기 위해 시스템을 Memory Hierarchy(메모리 계층 구조) 에 완벽하게 끼워 맞추는 전략을 취했습니다.
2. L3 캐시에 인덱스를 태우다: 계층적 클러스터링 & 양자화
이들의 전략은 ‘Approximation and Refinement(근사 후 정제)‘입니다. 뻔한 전략 같지만, 디테일이 다릅니다.
SPFresh 기반의 계층적 클러스터링
먼저 전체 벡터 공간을 클러스터링해서 트리 구조로 만듭니다. 중요한 건 이 트리의 Branching Factor(분기 계수) 를 100으로 잡았다는 겁니다. 왜 100일까요? DRAM과 SSD의 크기 비율이 대략 10~50배 정도 되기 때문입니다. 즉, 하드웨어 스펙에 맞춰 트리 구조를 짠 겁니다.
Binary Quantization (RaBitQ)
이게 핵심입니다. f16(2byte) 벡터를 1-bit로 압축해버립니다. 16~32배 압축이죠. 이렇게 압축하면 무슨 일이 벌어지느냐?
- L3 Cache: 트리의 상위 레벨(Centroid)이 통째로 CPU L3 캐시에 들어갑니다.
- DRAM: 압축된 데이터 벡터가 메모리에 상주합니다.
- NVMe SSD: 원본(Full precision) 벡터는 SSD에 두고, 필요할 때만 읽습니다.
계산을 때려보면, 양자화 덕분에 이론상 처리량(Throughput)이 100 QPS에서 10,000 QPS로 100배 뜁니다. 데이터를 작게 만드니 대역폭(Bandwidth) 문제가 해결된 거죠.
3. 반전: 너무 압축해서 CPU가 터지다 (Compute-bound)
여기서 엔지니어링의 묘미가 나옵니다. 데이터를 너무 효율적으로 압축해서 대역폭 문제를 해결했더니, 이제는 CPU가 압축을 풀고 비트 연산을 하느라 지쳐버린 겁니다. 시스템이 Memory-bound에서 Compute-bound로 성격이 바뀌어버린 거죠.
특히 RaBitQ 알고리즘은 비트 단위 연산이 엄청나게 많습니다. 프로덕션 환경에서 기대 성능의 10%인 1,000 QPS밖에 안 나오는 상황.
해결책: AVX-512 VPOPCNTDQ
이들은 x86 SIMD 명령어 세트까지 파고듭니다. AVX2에는 비트 개수를 세는 popcount 가속 명령어가 없다는 걸 발견하고, AVX-512 를 도입합니다. VPOPCNTDQ 명령어를 사용하니 512비트 레지스터의 비트 수를 단 3사이클 만에 세버립니다.
이 명령어 하나로 커널 성능을 30% 올리고, 전체 처리량을 5% 개선했습니다. “Microbenchmark가 End-to-End 성능 향상으로 이어질 때, 진짜 병목을 찾은 것이다”라는 문구가 인상적이더군요.
4. Hacker News의 반응과 나의 생각
이 글에 대해 Hacker News(HN)의 반응도 뜨거웠습니다. 특히 “Postgres(pgvector)로 버티다가 깨지는 순간이 오면 그때 Turbopuffer로 가라” 는 의견이 지배적이었습니다. 저도 100% 동의합니다. 100B 스케일이 아니라면 굳이 이런 복잡한 시스템을 도입할 필요는 없으니까요.
논쟁: 로컬 개발 환경 (Local Dev Experience)
HN 댓글 중 가장 공감 갔던 부분은 “오프라인/로컬 개발 환경” 에 대한 논쟁이었습니다. Turbopuffer는 클라우드 네이티브라 로컬 시뮬레이터가 없습니다. 개발팀은 “테스트용 API 키를 써라”라고 하지만, 보안이 엄격한 CI 환경이나 비행기 안에서 코딩하고 싶은 개발자들에게는 분명한 진입 장벽입니다.
한 유저(anon)의 코멘트가 뼈를 때립니다:
“오프라인 개발 환경을 원하는 사람들은 불평을 하는 게 아니라, 조용히 당신네 서비스를 스킵하고 떠날 것이다.”
Qdrant 같은 오픈소스 기반 솔루션들이 사랑받는 이유가 바로 이 ‘로컬 경험’ 때문이죠. Turbopuffer가 엔지니어링적으로는 훌륭하지만, DX(Developer Experience) 측면에서는 아직 갈 길이 있어 보입니다.
결론: Scale이 깡패가 될 때
Turbopuffer ANN v3는 “스케일이 커지면 범용 솔루션(General Purpose)은 버리고, 하드웨어 바닥부터 다시 짜야 한다” 는 진리를 다시 한번 증명했습니다.
- 장점: 100B 스케일에서의 압도적인 성능, 하드웨어 리소스의 극한 효율화.
- 단점: 로컬 개발 환경의 부재, 클라우드 종속성.
여러분이 만약 ‘넥스트 구글’급의 검색 엔진이나 RAG 시스템을 만들고 있다면 Turbopuffer를 눈여겨보세요. 하지만 스타트업 초기 단계라면? 그냥 pgvector 쓰세요. 그게 정신 건강에 이롭습니다.