Presentamos Cardinal: el motor de mayor rendimiento para búsquedas vectoriales
Esta publicación está escrita por Alexandr Guzhva y Li Liu.
En las bases de datos, el 'rendimiento' es una métrica crítica, especialmente en las bases de datos vectoriales. Es fundamental para procesar eficientemente un alto volumen de solicitudes de usuarios con recursos limitados. Aunque la latencia de acceso podría no ser una preocupación en algunas situaciones, para una base de datos vectorial, el rendimiento sigue siendo esencial por diversas razones.
La búsqueda vectorial, dependiente de la Búsqueda Aproximada del Vecino Más Cercano (ANNS), puede intercambiar un ligero grado de precisión por un rendimiento mejorado. Un rendimiento mejorado, a su vez, permite una mayor precisión.
Un rendimiento sobresaliente, mantenido bajo una latencia de consulta constante, facilita un mayor rendimiento usando los mismos recursos, dando cabida a una base de usuarios más grande.
Además, un rendimiento mejorado se traduce en la necesidad de menos recursos computacionales para soportar escenarios de uso idénticos.
Las bases de datos vectoriales son inherentemente intensivas en computación, con una porción significativa del uso de recursos—a menudo superior al 80%—dedicada a cálculos de distancia vectorial. Como resultado, el motor de búsqueda vectorial, responsable de gestionar las tareas de búsqueda vectorial, se convierte en un factor crítico para determinar el rendimiento general de una base de datos vectorial.
Zilliz prioriza constantemente la mejora del rendimiento de las bases de datos vectoriales. El Milvus de código abierto y el Zilliz Cloud totalmente gestionado demuestran un rendimiento superior en comparación con productos similares. El motor de búsqueda vectorial de Milvus Knowhere, desempeña un papel importante en lograr este éxito al sentar las bases para un nuevo motor de búsqueda.
En el centro de la última versión de Zilliz Cloud está Cardinal, un nuevo motor de búsqueda vectorial que construimos. Este motor de búsqueda ya ha demostrado un aumento de rendimiento de tres veces en comparación con la versión anterior, ofreciendo un rendimiento de búsqueda (QPS) que alcanza diez veces el de Milvus.
Evaluamos el rendimiento más reciente de Zilliz Cloud mediante la herramienta de benchmark de bases de datos vectoriales de código abierto y comparamos su rendimiento con Milvus y Zilliz Cloud con un motor antiguo. Los resultados de la evaluación se muestran en los gráficos a continuación.
¿Qué es Cardinal?
Cardinal es un motor de búsqueda vectorial propietario, multiproceso, moderno y basado en plantillas C++ que implementa los métodos ANNS más prácticos y ampliamente utilizados. Cardinal fue diseñado y escrito desde cero para utilizar eficientemente los recursos de cómputo disponibles.
Cardinal es capaz de:
realizar búsqueda de fuerza bruta,
crear y modificar índices ANNS,
realizar búsqueda Top-K de índice y búsqueda de rango de índice,
trabajar con varios formatos de datos de entrada, incluidos FP32, FP16 y BF16,
trabajar con datos en memoria o con datos mapeados en memoria,
filtrar los resultados durante la búsqueda según criterios proporcionados por el usuario.
Cardinal incluye:
Una implementación de métodos ANN que permite una configuración sencilla de varios parámetros internos. Sin embargo, el punto operativo predeterminado se ajusta constantemente para maximizar la velocidad de búsqueda (QPS, consultas por segundo) mientras se mantiene una precisión razonable (tasa de recuperación).
Implementación eficiente de varios algoritmos que soportan métodos ANNS. Por ejemplo, aquellos que proporcionan capacidades de filtrado de muestras.
Kernels optimizados especializados de bajo nivel para la mayoría de las operaciones intensivas en cómputo utilizadas durante la búsqueda o la construcción. Se admiten múltiples plataformas de hardware. Además de kernels que calculan distancias para diversas métricas, Cardinal también contiene kernels fusionados y kernels para el preprocesamiento de datos.
Instalaciones de soporte, como operaciones asincrónicas, capacidades de E/S mapeada en memoria, almacenamiento en caché, asignadores de memoria, registro, etc.
Knowhere vs Cardinal
La biblioteca Knowhere es un núcleo interno de Milvus de código abierto, responsable de la búsqueda vectorial. Knowhere se basa en versiones parcheadas de bibliotecas de código abierto estándar de la industria, como Faiss, DiskANN y hnswlib.
Proporcionemos una comparación entre Knowhere y Cardinal:
| Característica | Knowhere | Cardinal |
|---|---|---|
| Preparación para producción | Sí | Sí |
| Capacidades de escalabilidad | Sí | Sí |
| Filosofía de diseño | Experimentación y flexibilidad | Alcance limitado, prioriza la mejora de las características existentes para el rendimiento |
| Compatibilidad con hosts | Todos los tipos de hosts | Optimizado para el entorno de host de Zilliz Cloud |
| Dependencia | Depende de bibliotecas e implementaciones OSS conocidas | Contiene modificaciones y optimizaciones no triviales |
Ambos están listos para producción y proporcionan todas las capacidades de escalabilidad que Milvus y Zilliz Cloud necesitan.
Knowhere está diseñado pensando en la experimentación y la flexibilidad. Cardinal tiene un alcance más limitado, priorizando la mejora de las características existentes para una mayor velocidad y rendimiento en lugar de introducir una amplia funcionalidad nueva.
Dado que Knowhere es de código abierto y puede implementarse en muchos entornos diferentes, se ejecuta en todos los tipos de hosts. Cardinal está optimizado para el entorno de host de Zilliz Cloud.
Knowhere depende de bibliotecas e implementaciones OSS conocidas(como Faiss, DiskANN y hnswlib). Cardinal contiene modificaciones y optimizaciones no triviales.
Qué hace que Cardinal sea tan rápido
Cardinal implementa diversas optimizaciones relacionadas con algoritmos, de ingeniería y de bajo nivel. Cardinal introduce el mecanismo AUTOINDEX, que selecciona automáticamente la mejor estrategia de búsqueda e índice para el conjunto de datos. Esto elimina la necesidad de ajuste manual, ahorrando tiempo y esfuerzo a los desarrolladores.
Profundicemos en los detalles.
Optimizaciones de algoritmos
Esta forma de optimización mejora significativamente la precisión y la eficacia del proceso de búsqueda, una canalización multifacética que involucra varios algoritmos trabajando en conjunto. Numerosos algoritmos dentro de esta canalización pueden refinarse para impulsar el rendimiento general. Entre los candidatos destacados para optimizaciones de algoritmos dentro de Cardinal se incluyen:
Algoritmos de búsqueda, que abarcan enfoques basados tanto en IVF como en grafos,
Algoritmos diseñados para ayudar a que la búsqueda mantenga la tasa de recuperación requerida, independientemente del porcentaje de muestras filtradas,
Iteraciones avanzadas de algoritmos de búsqueda best-first,
Algoritmos personalizados para una estructura de datos de cola de prioridad.
Los algoritmos parametrizables proporcionan la flexibilidad para hacer compensaciones, como equilibrar el rendimiento frente al uso de RAM. Como resultado, las optimizaciones de algoritmos para Cardinal también implican seleccionar puntos de operación óptimos dentro del espacio de parámetros.
Optimizaciones de ingeniería
Aunque los algoritmos se diseñan inicialmente pensando en máquinas de Turing abstractas, la implementación en el mundo real se enfrenta a desafíos como latencias de red, restricciones de los proveedores de nube sobre IOPS y limitaciones de la RAM de las máquinas, un recurso valioso pero finito.
Las optimizaciones de ingeniería garantizan que el pipeline de búsqueda vectorial de Cardinal siga siendo práctico y se alinee con las restricciones de cómputo, RAM y otros recursos. En el desarrollo de Cardinal, combinamos prácticas estándar y técnicas innovadoras. Este enfoque permite que el compilador de C++ genere código compilado computacionalmente óptimo, manteniendo al mismo tiempo un código fuente limpio, medible con benchmarks y fácilmente extensible, que facilita la rápida incorporación de nuevas funcionalidades.
Estos son algunos ejemplos de prácticas de ingeniería implementadas en Cardinal, que muestran optimizaciones específicas:
Asignadores de memoria especializados y pools de memoria,
Código multihilo correctamente implementado,
Una estructura jerárquica de componentes que facilita la combinación de elementos en diversos pipelines de búsqueda,
Personalización del código para casos de uso específicos y críticos.
Optimizaciones de bajo nivel
La mayor parte del tiempo de búsqueda se dedica a piezas de código relativamente pequeñas conocidas como kernels. El ejemplo más sencillo es un kernel que calcula la distancia L2 entre dos vectores.
Cardinal incluye numerosos kernels de cómputo para diferentes propósitos, cada uno escrito y optimizado específicamente para una plataforma de hardware y un caso de uso concretos.
Cardinal admite plataformas de hardware x86 y ARM, pero otras plataformas pueden añadirse fácilmente.
Para la plataforma x86, los kernels de Cardinal utilizan las extensiones F, CD, VL, BW, DQ, VPOPCNTDQ, VBMI, VBMI2, VNNI, BF16 y FP16 de AVX-512. Además, estamos explorando el uso de un nuevo conjunto de instrucciones AMX.
Para la plataforma ARM, los kernels de Cardinal están disponibles tanto para los conjuntos de instrucciones NEON como SVE.
Nos aseguramos de que Cardinal obtenga el código más óptimo para los kernels de cómputo. No dependemos simplemente de que un compilador moderno de C++ haga el trabajo:
Utilizamos herramientas dedicadas, como Linux perf, para analizar hotspots y métricas de CPU
Utilizamos herramientas de análisis de código máquina, como GodBolt Compiler Explorer y uiCA, para garantizar el uso óptimo de los ‘recursos’ de hardware, como el número de accesos a RAM/caché, instrucciones de CPU usadas, registros y puertos de cómputo.
Utilizamos un enfoque iterativo que intercala las etapas de diseño, benchmarking, profiling y análisis de código ensamblador.
Un kernel de cómputo correctamente optimizado puede proporcionar una aceleración de 2x o 3x en comparación con un kernel ingenuo pero no optimizado. Esto puede traducirse además en un valor de QPS 2x mayor o en requisitos de memoria un 20% menores en una máquina host en la nube.
AutoIndex: selección de estrategia de búsqueda
La búsqueda vectorial es un proceso complejo que involucra muchos componentes independientes, incluyendo cuantización, construcción de índices, algoritmos de búsqueda, estructuras de datos y más. Cada componente tiene una multitud de parámetros ajustables. En conjunto, forman una gama muy variada de estrategias de búsqueda vectorial, y distintos conjuntos de datos y escenarios requieren diferentes estrategias de búsqueda.
Para aprovechar mejor el potencial de mejora del rendimiento, Cardinal, además de admitir múltiples estrategias en cada componente, ha implementado un conjunto de mecanismos de selección dinámica de estrategias basados en IA conocidos como AUTOINDEX. Elige de forma adaptativa la estrategia más adecuada en función de la distribución del conjunto de datos dado, la consulta proporcionada y la configuración de hardware. Esto nos ayuda a lograr un rendimiento óptimo al tiempo que satisfacemos las demandas de los usuarios en cuanto a calidad de búsqueda.
Benchmark de Cardinal
Hemos adoptado ANN-benchmarks para admitir Cardinal en nuestro entorno de pruebas. ANN benchmarks es una herramienta de evaluación comparativa estándar para evaluar implementaciones de ANNS, y se ejecuta en varios conjuntos de datos estándar que utilizan diferentes métricas de distancia. Cada evaluación de rendimiento se realiza dentro de un contenedor docker restringido al uso de un solo hilo. Las métricas se basan en varias iteraciones de evaluación, que utilizan numerosas solicitudes de consulta únicas. Los resultados de cada framework evaluado se agregan en una frontera de Pareto de recall frente a QPS.
Todas las pruebas se realizaron en el mismo tipo de máquina que la referencia ann-benchmarks (a enero de 2024), que es una máquina Amazon EC2 r6i.16xlarge con la siguiente configuración:
CPU: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
Número de núcleos de CPU: 32
Hyperthreading está deshabilitado
RAM: 512 GB
SO: Ubuntu 22.04.3 LTS con kernel de Linux 6.2.0-1017-aws
El soporte para páginas enormes no estaba habilitado.
Las pruebas se ejecutaron con la opción `--parallelism=31`.
Cardinal se compiló usando el compilador clang 17.0.6.
Los resultados de benchmark presentados a continuación son solo para el motor Cardinal y no incluyen optimizaciones adicionales no relacionadas con índices proporcionadas por Zilliz Cloud.
Nota: Los resultados que sí incluyen optimizaciones específicas de Zilliz Cloud se proporcionan arriba, al comienzo del artículo.
Los siguientes gráficos se produjeron tomando las imágenes de los gráficos con resultados presentados en la página de GitHub de ANN-benchmark y añadiendo con precisión una curva adicional de Cardinal encima.
Para todos los benchmarks proporcionados, Cardinal muestra resultados muy competitivos. Y hay margen para seguir mejorando.
¿Qué sigue?
El futuro nos traerá nuevos desafíos, sin duda. Diferentes requisitos, diferentes cuellos de botella, conjuntos de datos más grandes. Seguimos trabajando para hacer que Cardinal sea aún mejor.
El camino está iluminado. La ruta está clara. Solo necesitamos la fuerza para seguirla :)
Sigue leyendo

Democratizing AI: Making Vector Search Powerful and Affordable
Zilliz democratizes AI vector search with Milvus 2.6 and Zilliz Cloud for powerful, affordable scalability, cutting costs in infrastructure, operations, and development.

Balancing Precision and Performance: How Zilliz Cloud's New Parameters Help You Optimize Vector Search
Optimize vector search with Zilliz Cloud’s level and recall features to tune accuracy, balance performance, and power AI applications.

AI Integration in Video Surveillance Tools: Transforming the Industry with Vector Databases
Discover how AI and vector databases are revolutionizing video surveillance with real-time analysis, faster threat detection, and intelligent search capabilities for enhanced security.



