¿Qué potencia la búsqueda de similitudes en la base de datos vectorial Milvus?
imagen de portada
Este artículo ha sido escrito por Yudong Cai y traducido por Angela Ni.
Como motor central de ejecución vectorial, Knowhere es para Milvus lo que un motor es para un coche deportivo. Este artículo presenta qué es Knowhere, en qué se diferencia de Faiss y cómo está estructurado el código de Knowhere.
Saltar a:
- El concepto de Knowhere
- Knowhere en la arquitectura Milvus
- Knowhere vs Faiss
- Entendiendo el código de Knowhere
- Añadir índices a Knowhere
El concepto de Knowhere
Estrechamente hablando, Knowhere es una interfaz de operación para acceder a los servicios en las capas superiores del sistema y las bibliotecas de búsqueda de similitud vectorial como Faiss, Hnswlib, Annoy en las capas inferiores del sistema. Además, Knowhere también se encarga de la computación heterogénea. Más concretamente, Knowhere controla en qué hardware (por ejemplo, CPU o GPU) se ejecutan las solicitudes de creación y búsqueda de índices. Así es como Knowhere obtiene su nombre - sabiendo dónde ejecutar las operaciones. Más tipos de hardware incluyendo DPU y TPU serán soportados en futuras versiones.
En un sentido más amplio, Knowhere también incorpora otras bibliotecas de índices de terceros como Faiss. Por lo tanto, en su conjunto, Knowhere es reconocido como el motor central de computación vectorial en la base de datos vectorial Milvus.
Desde el concepto de Knowhere, podemos ver que sólo procesa tareas de computación de datos, mientras que aquellas tareas como sharding, balance de carga, recuperación de desastres están más allá del ámbito de trabajo de Knowhere.
A partir de Milvus 2.0.1, Knowhere (en sentido amplio) se independiza del proyecto Milvus.
Knowhere en la arquitectura Milvus
arquitectura de knowhere
La computación en Milvus involucra principalmente operaciones vectoriales y escalares. Knowhere sólo maneja las operaciones sobre vectores en Milvus. La figura anterior ilustra la arquitectura Knowhere en Milvus.
La capa inferior es el hardware del sistema. Las bibliotecas de índices de terceros están sobre el hardware. Luego Knowhere interactúa con el nodo de índice y el nodo de consulta en la parte superior a través de CGO.
Este artículo habla de Knowhere en su sentido más amplio, como se marca dentro del marco azul en la ilustración de la arquitectura.
Knowhere Vs Faiss
Knowhere no sólo amplía las funciones de Faiss sino que también optimiza el rendimiento. Más específicamente, Knowhere tiene las siguientes ventajas.
1. Soporte para BitsetView
Inicialmente, bitset fue introducido en Milvus con el propósito de "borrado suave". Un vector borrado suavemente aún existe en la base de datos pero no será computado durante una búsqueda o consulta de similitud de vectores. Cada bit del conjunto de bits corresponde a un vector indexado. Si un vector está marcado como "1" en el conjunto de bits, significa que se ha eliminado de forma suave y que no participará en la búsqueda de vectores.
Los parámetros del conjunto de bits se agregan a todas las API de consulta de índice Faiss expuestas en Knowhere, incluidos los índices de CPU y GPU.
Obtenga más información sobre cómo bitset permite la versatilidad de la búsqueda vectorial.
2. Soporte para más métricas de similitud para indexar vectores binarios
Además de Hamming, Knowhere también soporta Jaccard, Tanimoto, Superestructura, Subestructura. Jaccard y Tanimoto pueden utilizarse para medir la similitud entre dos conjuntos de muestras mientras que Superestructura y Subestructura pueden utilizarse para medir la similitud de estructuras químicas.
3. Soporte para el conjunto de instrucciones AVX512
Faiss soporta múltiples conjuntos de instrucciones incluyendo AArch64, SSE4.2, AVX2. Knowhere amplía los conjuntos de instrucciones soportados añadiendo AVX512, que puede mejorar el rendimiento de la creación de índices y consultas entre un 20% y un 30% en comparación con AVX2.
4. Selección automática de instrucciones SIMD
Knowhere está diseñado para funcionar bien en un amplio espectro de procesadores CPU (tanto en plataformas locales como en la nube) con diferentes instrucciones SIMD (por ejemplo, SIMD SSE, AVX, AVX2 y AVX512). Por lo tanto, el reto es, dada una única pieza de software binario (es decir, Milvus), ¿cómo hacer que invoque automáticamente las instrucciones SIMD adecuadas en cualquier procesador de CPU? Faiss no admite la selección automática de instrucciones SIMD y los usuarios deben especificar manualmente la bandera SIMD (por ejemplo, "-msse4") durante la compilación. Sin embargo, Knowhere se construye mediante la refactorización del código base de Faiss. Las funciones comunes (por ejemplo, el cálculo de similitudes) que dependen de las aceleraciones SIMD se eliminan. Luego, para cada función, se implementan cuatro versiones (es decir, SSE, AVX, AVX2, AVX512) y cada una se coloca en un archivo fuente separado. A continuación, los archivos fuente se compilan individualmente con el indicador SIMD correspondiente. Por lo tanto, en tiempo de ejecución, Knowhere puede elegir automáticamente las instrucciones SIMD más adecuadas basándose en las banderas actuales de la CPU y luego enlazar los punteros de función correctos utilizando hooking.
5. Otras optimizaciones de rendimiento
Lea Milvus: A Purpose-Built Vector Data Management System para más información sobre la optimización del rendimiento de Knowhere.
Entendiendo el código Knowhere
Como se mencionó en la primera sección, Knowhere sólo maneja operaciones de búsqueda de vectores. Por lo tanto, Knowhere sólo procesa el campo vectorial de una entidad (actualmente, sólo se admite un campo vectorial para entidades en una colección). La construcción de índices y la búsqueda de similitud vectorial también se dirigen al campo vectorial de un segmento. Para tener una mejor comprensión del modelo de datos, lea el blog aquí.
campos de entidad
Índice
El índice es un tipo de estructura de datos independiente de los datos vectoriales originales. La indexación requiere cuatro pasos: crear un índice, entrenar datos, insertar datos y construir un índice.
Para algunas de las aplicaciones de IA, el entrenamiento del conjunto de datos es un proceso independiente de la búsqueda de vectores. En este tipo de aplicaciones, los datos de los conjuntos de datos se entrenan primero y luego se insertan en una base de datos vectorial como Milvus para la búsqueda de similitudes. Los conjuntos de datos abiertos como sift1M y sift1B proporcionan datos para el entrenamiento y las pruebas. Sin embargo, en Knowhere, los datos para el entrenamiento y la búsqueda se mezclan. Es decir, Knowhere entrena todos los datos en un segmento y luego inserta todos los datos entrenados y construye un índice para ellos.
Estructura del código Knowhere
DataObj es la clase base de todas las estructuras de datos en Knowhere. Size()
es el único método virtual en DataObj. La clase Index hereda de DataObj con un campo llamado "size_". La clase Index también tiene dos métodos virtuales - Serialize()
y Load()
. La clase VecIndex derivada de Index es la clase base virtual para todos los índices vectoriales. VecIndex proporciona métodos como Train()
, Query()
, GetStatistics()
, y ClearStatistics()
.
clase base
Otros tipos de índices se enumeran a la derecha en la figura anterior.
- El índice Faiss tiene dos subclases: FaissBaseIndex para todos los índices sobre vectores en coma flotante, y FaissBaseBinaryIndex para todos los índices sobre vectores binarios.
- GPUIndex es la clase base para todos los índices Faiss GPU.
- OffsetBaseIndex es la clase base para todos los índices de desarrollo propio. En el archivo de índice sólo se almacena el ID del vector. Como resultado, el tamaño de un fichero de índices para vectores de 128 dimensiones puede reducirse en 2 órdenes de magnitud. Recomendamos tener en cuenta también los vectores originales cuando se utilice este tipo de índice para la búsqueda de similitud vectorial.
IDMAP
Técnicamente hablando, IDMAP no es un índice, sino que se utiliza para la búsqueda por fuerza bruta. Cuando se insertan vectores en la base de datos de vectores, no es necesario entrenar los datos ni construir el índice. Las búsquedas se realizarán directamente sobre los datos vectoriales insertados.
Sin embargo, en aras de la coherencia del código, IDMAP también hereda de la clase VecIndex con todas sus interfaces virtuales. El uso de IDMAP es el mismo que el de otros índices.
IVF
Los índices IVF (archivo invertido) son los más utilizados. La clase IVF deriva de VecIndex y FaissBaseIndex, y se extiende a IVFSQ e IVFPQ. GPUIVF deriva de GPUIndex e IVF. GPUIVF se extiende a GPUIVFSQ y GPUIVFPQ.
IVFSQHybrid es una clase de índice híbrido de desarrollo propio que se ejecuta mediante cuantificación gruesa en la GPU. Y la búsqueda en el cubo se ejecuta en la CPU. Este tipo de índice puede reducir la aparición de copias de memoria entre CPU y GPU aprovechando la potencia de cálculo de la GPU. IVFSQHybrid tiene la misma tasa de recuperación que GPUIVFSQ, pero presenta un mejor rendimiento.
La estructura de clases base de los índices binarios es relativamente más sencilla. BinaryIDMAP y BinaryIVF derivan de FaissBaseBinaryIndex y VecIndex.
índice de terceros
Actualmente, sólo se soportan dos tipos de índices de terceros aparte de Faiss: el índice basado en árbol Annoy, y el índice basado en grafo HNSW. Estos dos índices de terceros comunes y de uso frecuente se derivan de VecIndex.
Añadir índices a Knowhere
Si desea añadir nuevos índices a Knowhere, puede referirse primero a los índices existentes:
- Para añadir un índice basado en cuantización, consulte IVF_FLAT.
- Para añadir un índice basado en gráficos, consulte HNSW.
- Para añadir un índice basado en árboles, consulte Annoy.
Después de referirse al índice existente, puede seguir los siguientes pasos para agregar un nuevo índice a Knowhere.
- Añada el nombre del nuevo índice en
IndexEnum
. El tipo de datos es cadena. - Agregue la comprobación de validación de datos en el nuevo índice en el archivo
ConfAdapter.cpp
. La comprobación de validación es principalmente para validar los parámetros para la formación de datos y consulta. - Cree un nuevo archivo para el nuevo índice. La clase base del nuevo índice debe incluir
VecIndex
, y la interfaz virtual necesaria deVecIndex
. - Añade la lógica de construcción del nuevo índice en
VecIndexFactory::CreateVecIndex()
. - Añada la prueba unitaria en el directorio
unittest
.
Acerca de la serie Deep Dive
Con el anuncio oficial de la disponibilidad general de Milvus 2.0, orquestamos esta serie de blogs Milvus Deep Dive para ofrecer una interpretación en profundidad de la arquitectura y el código fuente de Milvus. Los temas tratados en esta serie de blogs incluyen
- El concepto de Knowhere
- Knowhere en la arquitectura Milvus
- Knowhere Vs Faiss
- Entendiendo el código Knowhere
- Añadir índices a Knowhere
- Acerca de la serie Deep Dive
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word