TurboQuant 기반 Rust 벡터 인덱스, 10M 문서 4GB로 압축
turbovec는 Google의 TurboQuant를 Rust로 구현하고 Python 바인딩을 제공하여 10M 문서를 4GB로 압축하면서 FAISS 대비 빠른 검색을 목표로 하는 벡터 인덱스이다.
TL;DR
turbovec는 TurboQuant 알고리즘을 Rust로 구현하고 Python 바인딩을 제공하는 벡터 인덱스로서 벡터 노름을 분리하고 임의 회전과 좌표별 보정을 통해 데이터 의존적 학습 없이 스칼라 양자화를 적용한다. 이 과정에서 Lloyd-Max 코드북과 길이 재정규화 보정을 결합하여 2~4비트 압축을 가능하게 하고, SIMD(NEON/AVX-512BW) 기반 니블-LUT 커널로 디코드 없이 고속 점수 계산을 수행한다. README의 벤치마크는 10M 문서 예시에서 float32 대비 31GB→4GB의 메모리 절감과 ARM에서 FAISS 대비 10~19%의 처리량 우위를 보고하며 OpenAI 차원에서 R@1이 0.2~1.9pp 향상되는 점을 제시한다. 결과적으로 온라인 인제스트와 커널 수준 필터링을 필요로 하는 프라이버시 민감 또는 메모리 제약 환경에서 기존 FAISS 계열보다 메모리-성능 트레이드오프가 유리하지만, x86 2비트 경로에서는 FAISS의 특정 AVX-512 VBMI 최적화가 근소한 우위를 보이는 점이 트레이드오프가 된다.
주요 기능
- 온라인 인제스트를 지원하여 벡터를 추가하면 즉시 인덱싱되고 별도의 훈련 단계나 재빌드가 필요하지 않다. 이 동작은 각 좌표에 대해 첫 추가 시점에만 수행되는 TQ+ 보정과 사전 계산된 Lloyd-Max 코드북을 결합해 구현되며 이후 삽입은 기존 코드 규칙을 적용해 빠르게 처리된다. 덕분에 대용량 코퍼스가 성장하는 환경에서도 지속적인 가용성과 낮은 운영 오버헤드를 유지할 수 있다.
- SIMD 최적화 검색 커널을 제공하여 NEON(ARM)과 AVX-512BW(x86) 경로에서 높은 처리량을 달성한다. 커널은 니블 기반 LUT와 u16 누적기를 사용해 압축 코드에서 직접 점수를 계산하므로 전체 벡터를 복원하지 않아도 되며, AVX2 폴백으로 더 넓은 CPU 호환성을 보장한다. 벤치마크에서 ARM에서는 FAISS IndexPQFastScan 대비 10~19% 빠르며 x86에서는 4비트 설정에서 우위가 관찰되었다.
- 검색 시 필터링(allowlist 또는 슬롯 비트마스크)을 커널 레벨에서 처리하여 선택적 필터가 있는 하이브리드 검색에서도 과도한 오버패치 없이 정확한 상위-k 결과를 반환한다. 필터 적용은 32-벡터 블록 단위의 단축 경로(short-circuit)와 힙 삽입 시 비허용 슬롯 드랍으로 구현되어 소수의 허용 슬롯만 있는 경우 대부분의 SIMD 비용을 회피한다. 이 설계는 RAG 파이프라인에서 SQL이나 BM25 등 외부 후보 집합과 결합할 때 지연과 비용을 줄이는 데 유리하다.
- 저비트 양자화(2-bit, 4-bit)를 통해 메모리 사용량을 크게 줄이며 길이 재정규화 보정으로 양자화가 초래하는 내적 편향을 제거한다. 각 벡터 인코딩 시 원래 노름과 복원된 단위 방향의 내적을 계산해 보정 스칼라를 저장하고 검색 시 점수에 곱해 편향을 정정하므로 추가 저장 비용이나 쿼리 비용이 거의 없다. 이로 인해 낮은 비트폭에서 특히 회수율 손실이 줄어들고 전체 시스템의 실효적 정확도가 개선된다.
어떻게 동작하는가
turbovec는 입력 벡터의 노름을 분리해 단위 방향으로 정규화한 뒤 모든 벡터에 동일한 임의 직교 행렬을 곱해 좌표 분포를 예측 가능한 형태로 만든다. 각 좌표는 TQ+ 단계에서 첫 추가 시에 5/95% 분위수를 대상 분포에 맞추는 shift·scale 보정을 학습하고 고정된 Lloyd-Max 스칼라 양자화를 적용해 비트폭별 코드북을 얻는다. 검색 시에는 쿼리를 동일한 회전으로 변환한 뒤 코드북 값을 직접 참조하는 SIMD 기반 니블-LUT 점수 계산을 수행하고 인코딩 단계에서 저장한 길이 보정 스칼라를 곱해 내적 추정치의 편향을 제거한다.
해결 문제
대규모 임베딩 색인에서 부동소수점 저장이 야기하는 메모리 부담과 그에 따른 비용 문제를 해결한다. turbovec는 수천만 차원급 데이터셋을 2~4비트로 압축하여 메모리를 획기적으로 줄이며 검색 처리량을 높이고, 별도의 코드북 훈련이나 인덱스 리빌드 없이 온라인으로 삽입을 처리해 확장성을 확보한다. 또한 필터링을 커널 내부에서 처리해 하이브리드 재랭킹 워크플로에서 불필요한 오버패치와 재정렬 비용을 줄인다.
지금 주목받는 이유
최근 TurboQuant 원저 논문(arXiv)과 turbovec의 구현이 결합되어 메모리-성능 트레이드오프에 대한 현실적인 대안을 제시하고 있어 주목을 받았다. README가 제시한 벤치마크는 대형 임베딩(dim=1536/3072)에서 FAISS 대비 근소한 리콜 우위와 ARM에서 10~19%의 처리량 우위를 보고하고 있어 실무 적용 가능성을 뒷받침한다. 또한 LangChain·LlamaIndex·Haystack 등 주요 오픈소스 검색/파이프라인과의 통합을 문서로 제공해 기존 파이프라인에 대체품으로 도입하기 쉬운 점도 관심을 끈 요인이다.
차별점
- 온라인 비훈련 양자화 파이프라인을 제공하여 벡터를 추가할 때 코드북 재학습이나 인덱스 재구성이 필요하지 않다. 이 접근은 TQ+ 보정이 첫 삽입 시점에만 좌표별 shift·scale을 고정하고 이후 삽입은 동일 코드북을 적용하기 때문에 가능한 설계이며, 운영 중단 없이 규모를 늘릴 수 있다는 이점이 있다. 기존 PQ 방식은 일반적으로 코드북 학습이나 재구성이 필요해 대규모 온라인 삽입에서 운영 비용이 커지는 단점이 있다.
- 커널 수준의 필터링을 통해 허용 ID 집합이 작은 경우 대부분의 SIMD 비용을 회피하도록 설계되어 하이브리드 검색 파이프라인에서 효율성이 높다. 32-벡터 블록 단위의 빠른 단축 경로와 블록 내 비허용 슬롯 드랍은 외부 후보 집합으로 결과를 좁힌 뒤 내부에서 조밀한 재랭킹을 수행하는 워크플로에 적합하다. 이로 인해 필터링 조건이 엄격한 멀티테넌시나 시간 윈도우 기반 검색에서 오버패치 비용을 줄일 수 있다.
- 길이 재정규화 보정을 저장하고 검색 시 곱해 양자화가 도입한 내적의 하향 편향을 제거함으로써 저비트 설정에서 회수율을 보존한다. 이 보정은 인코딩 단계에서 한 번의 d 차원 내적을 계산하는 추가 비용만 요구하며 대규모 인덱스에서도 쿼리 비용과 저장 오버헤드를 거의 증가시키지 않는다. 그 결과 2비트·4비트 환경에서의 실무적 정확도가 개선되어 메모리 대비 성능이 우수하다.
사용 사례
- 메모리 비용이 제한된 온프레미스 또는 VPC 기반 RAG 스택에서 임베딩 저장공간을 크게 줄이면서 검색 처리량을 유지·향상시키는 용도로 적합하다. turbovec는 10M 문서를 float32로 저장했을 때의 메모리(31GB)를 4GB로 줄이는 예시를 제시하므로 스토리지·운영비 절감이 가능한 어플리케이션에 실질적 이득을 준다. 길이 보정과 온라인 인제스트 덕분에 지속적으로 문서를 추가해야 하는 로그형·도큐먼트형 저장소에 특히 유리하다.
- 하이브리드 검색 파이프라인에서 외부 후보 필터링(SQL·BM25·시간 윈도우 등) 뒤의 조밀 재랭킹 용도로 사용하면 필터 조건이 엄격한 상황에서도 쿼리 지연을 줄일 수 있다. turbovec의 커널 내 allowlist 처리는 작은 후보 집합에 대해 대부분의 SIMD 비용을 회피하므로 멀티테넌시·접근 제어 기반 검색에서 응답성 향상을 가져온다. 이 접근은 다단계 랭킹 아키텍처에서 첫 단계로 빠른 후보 검색을 대체하거나 보완하는 데 적합하다.
- 로컬·에어갭 환경에서 외부 관리 서비스를 사용하지 않고 자체 임베딩 모델과 결합해 완전한 프라이버시 보장 RAG 스택을 구성하는 데 활용할 수 있다. turbovec는 순수 로컬 인덱스이며 어떤 오픈소스 임베딩 모델과도 페어링 가능하므로 데이터 유출 위험을 최소화해야 하는 규제적 제약이 있는 서비스에 적용할 수 있다. 또한 Python 바인딩과 Rust 크레이트를 모두 제공하므로 다양한 배포 환경에 맞춰 성능과 편의성을 선택할 수 있다.
시작하기
PyPI에서 pip install turbovec로 빠르게 시작할 수 있으며, 예제처럼 TurboQuantIndex(dim=1536, bit_width=4)를 생성해 add·search·write·load API를 통해 기본 워크플로를 바로 실행할 수 있다. 소스에서 Python 바인딩을 빌드하려면 maturin을 사용해 turbovec-python 디렉토리에서 maturin build --release를 실행하고 생성된 wheel을 pip로 설치하면 된다. 자세한 API 참조와 프레임워크 통합 문서는 docs/api.md 및 integrations 문서에 수록되어 있어 기존 LangChain·LlamaIndex 파이프라인에 교체 적용하는 절차를 따라할 수 있다.
요구사항
- 런타임 CPU 기능으로 AVX2 이상의 명령어가 필요하거나 AVX-512를 지원하면 AVX-512BW 경로를 활용할 수 있다. README는 모든 x86_64 빌드가 x86-64-v3(target)로 타깃팅되며 AVX2 폴백을 통해 더 낮은 벤치마크 호환성을 제공한다고 명시한다. ARM 환경에서는 NEON 최적화가 포함되어 있어 Apple M 계열 같은 SIMD 지원 플랫폼에서 성능을 끌어낼 수 있다.
- Python 바인딩을 소스에서 빌드하려면 maturin이 필요하며 Rust toolchain과 관련 빌드 도구가 사전에 설치되어 있어야 한다. 바이너리 wheel을 사용할 경우 런타임 종속성은 최소화되지만, 소스 빌드는 플랫폼별 컴파일 환경을 요구하므로 CI나 배포 환경에서 사전 준비가 필요하다. 대규모 벤치마크 실행을 위해서는 충분한 메모리와 표준 벤치마크 데이터셋 다운로드 스크립트가 요구된다.
벤치마크
| 벤치마크 | 지표 | 값 | 비교 |
|---|---|---|---|
| Memory for 10M documents | RAM | 4 GB | vs float32: 31 GB |
| Search speed on ARM | throughput improvement | 10–19% faster than FAISS IndexPQFastScan | vs FAISS IndexPQFastScan |
| Recall R@1 across OpenAI dims | R@1 delta | 0.2–1.9 percentage points higher | vs FAISS IndexPQ |
13.5k
Stars
1.2k
Forks
+208
Trending
0
조회수
관련 토론
아직 관련 토론이 없습니다.
댓글
댓글을 작성하려면 로그인이 필요합니다.