🚀 완전 관리형 Milvus인 Zilliz Cloud를 무료로 체험해보세요—10배 더 빠른 성능을 경험하세요! 지금 체험하기>>

milvus-logo
LFAI

HomeBlogs밀버스 벡터 데이터베이스의 유사도 검색 기능은 무엇인가요?

밀버스 벡터 데이터베이스의 유사도 검색 기능은 무엇인가요?

  • Engineering
May 10, 2022
Yudong Cai

cover image 표지 이미지

이 글은 유동카이가 작성하고 안젤라 니가 번역했습니다.

핵심 벡터 실행 엔진인 Knowhere는 스포츠카의 엔진과 같은 역할을 합니다. 이 글에서는 Knowhere가 무엇인지, Faiss와 어떻게 다른지, 그리고 Knowhere의 코드가 어떻게 구성되어 있는지 소개합니다.

바로가기:

Knowhere의 개념

좁게 말하면, Knowhere는 시스템의 상위 계층에 있는 서비스와 하위 계층에 있는 Faiss, Hnswlib, Annoy와 같은 벡터 유사성 검색 라이브러리에 액세스하기 위한 작업 인터페이스입니다. 또한 Knowhere는 이기종 컴퓨팅도 담당합니다. 좀 더 구체적으로, Knowhere는 인덱스 구축과 검색 요청을 실행할 하드웨어(예: CPU 또는 GPU)를 제어합니다. 이것이 바로 작업을 실행할 위치를 파악한다는 의미에서 Knowhere라는 이름이 붙여진 이유입니다. 향후 릴리즈에서는 DPU와 TPU를 포함한 더 많은 유형의 하드웨어가 지원될 예정입니다.

더 넓은 의미에서, Knowhere는 Faiss와 같은 다른 타사 인덱스 라이브러리도 통합합니다. 따라서 전반적으로 Knowhere는 Milvus 벡터 데이터베이스의 핵심 벡터 계산 엔진으로 인식되고 있습니다.

Knowhere의 개념에서 보면 데이터 컴퓨팅 작업만 처리하고 샤딩, 로드 밸런스, 재해 복구와 같은 작업은 Knowhere의 작업 범위를 벗어난다는 것을 알 수 있습니다.

Milvus 2.0.1부터 (넓은 의미에서) Knowhere는 Milvus 프로젝트에서 독립됩니다.

Milvus 아키텍처의 Knowhere

knowhere architecture Knowhere 아키텍처

Milvus의 연산은 주로 벡터와 스칼라 연산을 포함합니다. Knowhere는 Milvus에서 벡터에 대한 연산만 처리합니다. 위 그림은 Milvus의 Knowhere 아키텍처를 보여줍니다.

가장 아래쪽 계층은 시스템 하드웨어입니다. 타사 인덱스 라이브러리는 하드웨어 위에 있습니다. 그런 다음 Knowhere는 CGO를 통해 상단의 인덱스 노드 및 쿼리 노드와 상호 작용합니다.

이 문서에서는 아키텍처 그림의 파란색 프레임 안에 표시된 대로 보다 넓은 의미의 Knowhere에 대해 설명합니다.

Knowhere 대 Faiss

Knowhere는 Faiss의 기능을 더욱 확장할 뿐만 아니라 성능도 최적화합니다. 보다 구체적으로 Knowhere는 다음과 같은 장점이 있습니다.

1. 비트셋뷰 지원

처음에 비트셋은 '소프트 삭제'를 목적으로 Milvus에 도입되었습니다. 소프트 삭제된 벡터는 데이터베이스에 여전히 존재하지만 벡터 유사도 검색이나 쿼리 중에 계산되지 않습니다. 비트 세트의 각 비트는 인덱싱된 벡터에 해당합니다. 벡터가 비트셋에서 "1"로 표시되어 있으면 이 벡터는 소프트 삭제된 벡터이며 벡터 검색 중에 포함되지 않는다는 뜻입니다.

비트셋 매개변수는 CPU 및 GPU 인덱스를 포함해 Knowhere에 노출된 모든 Faiss 인덱스 쿼리 API에 추가됩니다.

비트셋이 어떻게 벡터 검색의 다양성을 가능하게 하는지에 대해 자세히 알아보세요.

2. 바이너리 벡터 인덱싱을 위한 더 많은 유사성 메트릭 지원

해밍 외에도, Knowhere는 Jaccard, Tanimoto, 상위 구조, 하위 구조도 지원합니다. Jaccard와 Tanimoto는 두 샘플 세트 간의 유사성을 측정하는 데 사용할 수 있으며, 상부구조와 하부구조는 화학 구조의 유사성을 측정하는 데 사용할 수 있습니다.

3. AVX512 명령어 세트 지원

Faiss 자체는 AArch64, SSE4.2, AVX2를 포함한 여러 명령어 세트를 지원합니다. Knowhere는 AVX512를 추가하여 지원 명령어 세트를 더욱 확장했으며, 이를 통해 인덱스 구축 및 쿼리 성능을 AVX2에 비해 20~30% 향상시킬 수 있습니다.

4. 자동 SIMD 명령어 선택

Knowhere는 다양한 SIMD 명령어(예: SIMD SSE, AVX, AVX2, AVX512)를 가진 광범위한 CPU 프로세서(온프레미스 및 클라우드 플랫폼 모두)에서 잘 작동하도록 설계되었습니다. 따라서 하나의 소프트웨어 바이너리(예: Milvus)가 주어졌을 때, 어떻게 하면 모든 CPU 프로세서에서 적합한 SIMD 명령어를 자동으로 호출하도록 만들 수 있을까요? Faiss는 자동 SIMD 명령어 선택을 지원하지 않으며, 사용자는 컴파일 중에 SIMD 플래그(예: "-msse4")를 수동으로 지정해야 합니다. 그러나 Knowhere는 Faiss의 코드베이스를 리팩토링하여 구축되었습니다. SIMD 가속에 의존하는 일반적인 함수(예: 유사성 컴퓨팅)는 제외됩니다. 그런 다음 각 기능에 대해 네 가지 버전(즉, SSE, AVX, AVX2, AVX512)을 구현하고 각각 별도의 소스 파일에 넣습니다. 그런 다음 소스 파일은 해당 SIMD 플래그를 사용하여 개별적으로 추가로 컴파일됩니다. 따라서 런타임에 Knowhere는 현재 CPU 플래그를 기반으로 가장 적합한 SIMD 명령어를 자동으로 선택한 다음 후킹을 사용하여 올바른 함수 포인터를 연결할 수 있습니다.

5. 기타 성능 최적화

Knowhere의 성능 최적화에 대한 자세한 내용은 밀버스: 특수 목적의 벡터 데이터 관리 시스템을 읽어보세요.

Knowhere 코드 이해하기

첫 번째 섹션에서 언급했듯이 Knowhere는 벡터 검색 연산만 처리합니다. 따라서 Knowhere는 엔티티의 벡터 필드만 처리합니다(현재는 컬렉션의 엔티티에 대해 하나의 벡터 필드만 지원됨). 인덱스 구축 및 벡터 유사성 검색도 세그먼트의 벡터 필드를 대상으로 합니다. 데이터 모델을 더 잘 이해하려면 여기에서 블로그를 읽어보세요.

entity fields 엔티티 필드

인덱스

인덱스는 원본 벡터 데이터와는 독립적인 데이터 구조의 일종입니다. 인덱싱에는 인덱스 생성, 데이터 학습, 데이터 삽입, 인덱스 구축의 네 단계가 필요합니다.

일부 AI 애플리케이션의 경우, 데이터 세트 학습은 벡터 검색의 개별 프로세스입니다. 이러한 유형의 애플리케이션에서는 데이터 세트의 데이터를 먼저 학습시킨 다음 유사성 검색을 위해 Milvus와 같은 벡터 데이터베이스에 삽입합니다. sift1M 및 sift1B와 같은 오픈 데이터 세트는 학습 및 테스트를 위한 데이터를 제공합니다. 그러나 Knowhere에서는 학습과 검색을 위한 데이터가 혼합되어 있습니다. 즉, Knowhere는 세그먼트의 모든 데이터를 학습시킨 다음 학습된 모든 데이터를 삽입하고 인덱스를 구축합니다.

Knowhere 코드 구조

DataObj는 Knowhere의 모든 데이터 구조의 기본 클래스입니다. Size() 는 DataObj의 유일한 가상 메서드입니다. Index 클래스는 "size_"라는 필드가 있는 DataObj를 상속합니다. Index 클래스에는 Serialize()Load() 라는 두 개의 가상 메서드도 있습니다. Index에서 파생된 VecIndex 클래스는 모든 벡터 인덱스의 가상 베이스 클래스입니다. VecIndex는 Train(), Query(), GetStatistics(), ClearStatistics() 등의 메서드를 제공합니다.

base clase 베이스 클래스

다른 인덱스 유형은 위 그림의 오른쪽에 나열되어 있습니다.

  • Faiss 인덱스에는 두 개의 서브 클래스가 있습니다: 부동 소수점 벡터의 모든 인덱스에 대한 FaissBaseIndex와 이진 벡터의 모든 인덱스에 대한 FaissBaseBinaryIndex입니다.
  • GPUIndex는 모든 Faiss GPU 인덱스의 베이스 클래스입니다.
  • OffsetBaseIndex는 모든 자체 개발 인덱스의 베이스 클래스입니다. 인덱스 파일에는 벡터 ID만 저장됩니다. 그 결과 128차원 벡터의 인덱스 파일 크기를 두 배로 줄일 수 있습니다. 벡터 유사도 검색에 이러한 유형의 인덱스를 사용할 때는 원본 벡터도 함께 고려하는 것이 좋습니다.

IDMAP IDMAP

엄밀히 말하면 IDMAP은 인덱스가 아니라 무차별 대입 검색에 사용됩니다. 벡터가 벡터 데이터베이스에 삽입되면 데이터 트레이닝과 인덱스 구축이 필요하지 않습니다. 검색은 삽입된 벡터 데이터에서 바로 수행됩니다.

그러나 코드 일관성을 위해 IDMAP은 모든 가상 인터페이스가 포함된 VecIndex 클래스에서도 상속됩니다. IDMAP의 사용법은 다른 인덱스와 동일합니다.

IVF IVF

IVF(반전 파일) 인덱스는 가장 자주 사용됩니다. IVF 클래스는 VecIndex와 FaissBaseIndex에서 파생되며, 더 나아가 IVFSQ와 IVFPQ로 확장됩니다. GPUIVF는 GPUIndex와 IVF에서 파생됩니다. 그런 다음 GPUIVF는 GPUIVFSQ 및 GPUIVFPQ로 더 확장됩니다.

IVFSQHybrid는 자체 개발한 하이브리드 인덱스를 위한 클래스로 GPU에서 거친 양자화를 통해 실행됩니다. 그리고 버킷에서의 검색은 CPU에서 실행됩니다. 이러한 유형의 인덱스는 GPU의 연산 능력을 활용하여 CPU와 GPU 간의 메모리 복사 발생을 줄일 수 있습니다. IVFSQHybrid는 GPUIVFSQ와 동일한 리콜률을 가지지만 더 나은 성능을 제공합니다.

바이너리 인덱스의 베이스 클래스 구조는 상대적으로 더 간단합니다. BinaryIDMAP과 BinaryIVF는 FaissBaseBinaryIndex와 VecIndex에서 파생됩니다.

third-party index 서드파티 인덱스

현재 Faiss를 제외하고 지원되는 타사 인덱스는 트리 기반 인덱스인 Annoy와 그래프 기반 인덱스인 HNSW의 두 가지 유형뿐입니다. 이 두 가지 일반적이고 자주 사용되는 서드파티 인덱스는 모두 VecIndex에서 파생된 것입니다.

Knowhere에 인덱스 추가하기

Knowhere에 새 인덱스를 추가하려면 먼저 기존 인덱스를 참조하면 됩니다:

  • 양자화 기반 인덱스를 추가하려면 IVF_FLAT을 참조하세요.
  • 그래프 기반 인덱스를 추가하려면 HNSW를 참조하세요.
  • 트리 기반 인덱스를 추가하려면 Annoy를 참조하세요.

기존 인덱스를 참조한 후, 아래 단계에 따라 Knowhere에 새 인덱스를 추가할 수 있습니다.

  1. 새 인덱스의 이름을 IndexEnum 에 추가합니다. 데이터 유형은 문자열입니다.
  2. ConfAdapter.cpp 파일에서 새 인덱스에 데이터 유효성 검사를 추가합니다. 유효성 검사는 주로 데이터 학습 및 쿼리를 위한 매개변수의 유효성을 검사하기 위한 것입니다.
  3. 새 인덱스에 대한 새 파일을 만듭니다. 새 인덱스의 베이스 클래스에는 VecIndex 과 필요한 가상 인터페이스 VecIndex 가 포함되어야 합니다.
  4. VecIndexFactory::CreateVecIndex() 에 새 인덱스에 대한 인덱스 구축 로직을 추가합니다.
  5. unittest 디렉토리에 단위 테스트를 추가합니다.

심층 분석 시리즈 소개

Milvus 2.0의 공식 출시 발표와 함께, Milvus 아키텍처와 소스 코드에 대한 심도 있는 해석을 제공하기 위해 Milvus 심층 분석 블로그 시리즈를 기획했습니다. 이 블로그 시리즈에서 다루는 주제는 다음과 같습니다:

Like the article? Spread the word

계속 읽기