Представляем Cardinal: самый производительный движок для векторного поиска
Этот пост написан Александром Гужвой и Ли Лю.
В базах данных «производительность» — критически важная метрика, особенно в векторных базах данных. Она играет ключевую роль в эффективной обработке большого объема пользовательских запросов при ограниченных ресурсах. Хотя задержка доступа в некоторых ситуациях может не быть проблемой, для векторной базы данных производительность остается важной по разным причинам.
Векторный поиск, опирающийся на поиск приближенных ближайших соседей (ANNS), может жертвовать небольшой долей точности ради повышения производительности. Улучшенная производительность, в свою очередь, позволяет добиться большей точности.
Выдающаяся производительность, поддерживаемая при стабильной задержке запросов, обеспечивает более высокую пропускную способность при использовании тех же ресурсов, позволяя обслуживать более широкую пользовательскую базу.
Более того, улучшенная производительность означает необходимость в меньшем количестве вычислительных ресурсов для поддержки идентичных сценариев использования.
Векторные базы данных по своей природе требуют интенсивных вычислений, при этом значительная часть использования ресурсов — часто превышающая 80% — приходится на вычисления расстояний между векторами. В результате векторный поисковый движок, отвечающий за обработку задач векторного поиска, становится критическим фактором, определяющим общую производительность векторной базы данных.
Zilliz неизменно уделяет первоочередное внимание повышению производительности векторных баз данных. Open-source Milvus и полностью управляемый Zilliz Cloud демонстрируют превосходную производительность по сравнению с аналогичными продуктами. Векторный поисковый движок Milvus Knowhere играет значительную роль в достижении этого успеха, закладывая основу для нового поискового движка.
В основе последнего релиза Zilliz Cloud лежит Cardinal, новый векторный поисковый движок, который мы создали. Этот поисковый движок уже продемонстрировал трехкратное увеличение производительности по сравнению с предыдущей версией, обеспечивая поисковую производительность (QPS), достигающую десятикратного показателя Milvus.
Мы оценили производительность последней версии Zilliz Cloud с помощью open-source инструмента бенчмаркинга векторных баз данных и сравнили ее производительность с Milvus и Zilliz Cloud со старым движком. Результаты оценки показаны на диаграммах ниже.
Что такое Cardinal?
Cardinal — это проприетарный многопоточный современный векторный поисковый движок на основе шаблонов C++, реализующий наиболее практичные и широко используемые методы ANNS. Cardinal был спроектирован и написан с нуля для эффективного использования доступных вычислительных ресурсов.
Cardinal способен:
выполнять поиск полным перебором,
создавать и изменять индексы ANNS,
выполнять индексный поиск Top-K и индексный поиск по диапазону,
работать с различными форматами входных данных, включая FP32, FP16 и BF16,
работать с данными в памяти или с данными, отображенными в память,
фильтровать результаты во время поиска на основе критериев, предоставленных пользователем.
Cardinal включает:
Реализацию методов ANN, позволяющую легко настраивать различные внутренние параметры. Однако рабочая точка по умолчанию постоянно настраивается так, чтобы максимизировать скорость поиска (QPS, запросов в секунду) при сохранении разумной точности (показателя полноты).
Эффективную реализацию различных алгоритмов, поддерживающих методы ANNS. Например, тех, которые предоставляют возможности фильтрации выборки.
Низкоуровневые специализированные оптимизированные ядра для большинства наиболее вычислительно интенсивных операций, используемых во время поиска или построения. Поддерживаются несколько аппаратных платформ. Помимо ядер, вычисляющих расстояния для различных метрик, Cardinal также содержит объединенные ядра и ядра для предварительной обработки данных.
Вспомогательные средства, такие как асинхронные операции, возможности ввода-вывода с отображением в память, кэширование, распределители памяти, логирование и т. д.
Knowhere vs Cardinal
Библиотека Knowhere является внутренним ядром open-source Milvus, отвечающим за векторный поиск. Knowhere основана на пропатченных версиях стандартных для отрасли open-source библиотек, таких как Faiss, DiskANN и hnswlib.
Давайте приведем сравнение Knowhere и Cardinal:
| Функция | Knowhere | Cardinal |
|---|---|---|
| Готовность к production | Да | Да |
| Возможности масштабирования | Да | Да |
| Философия дизайна | Экспериментирование и гибкость | Узкая область применения, приоритет — улучшение существующих функций для повышения производительности |
| Совместимость с хостами | Все типы хостов | Оптимизирован для хост-среды Zilliz Cloud |
| Зависимости | Опирается на известные OSS-библиотеки и реализации | Содержит нетривиальные модификации и оптимизации |
Оба решения готовы к production и предоставляют все возможности масштабирования, необходимые Milvus и Zilliz Cloud.
Knowhere разработан с учетом экспериментирования и гибкости. Cardinal имеет более узкую область применения, отдавая приоритет улучшению существующих функций для повышения скорости и производительности, а не внедрению обширной новой функциональности.
Поскольку Knowhere является open-source и может быть развернут во множестве различных сред, он работает на всех типах хостов. Cardinal оптимизирован для хост-среды Zilliz Cloud.
Knowhere опирается на известные OSS-библиотеки и реализации(такие как Faiss, DiskANN и hnswlib). Cardinal содержит нетривиальные модификации и оптимизации.
Что делает Cardinal таким быстрым
Cardinal реализует различные оптимизации, связанные с алгоритмами, инженерией и низкоуровневым уровнем. Cardinal вводит механизм AUTOINDEX, который автоматически выбирает лучшую стратегию поиска и индекс для набора данных. Это устраняет необходимость ручной настройки, экономя время и усилия разработчиков.
Давайте углубимся в детали.
Оптимизации алгоритмов
Эта форма оптимизации значительно повышает точность и эффективность процесса поиска — многогранного конвейера, включающего различные алгоритмы, работающие совместно. Многие алгоритмы в этом конвейере можно доработать, чтобы повысить общую производительность. Среди заметных кандидатов для оптимизаций алгоритмов в Cardinal:
Алгоритмы поиска, охватывающие как подходы на основе IVF, так и графовые подходы,
Алгоритмы, разработанные для того, чтобы помочь поиску поддерживать требуемый уровень recall независимо от процента отфильтрованных образцов,
Продвинутые итерации алгоритмов best-first search,
Настраиваемые алгоритмы для структуры данных priority queue.
Параметризуемые алгоритмы обеспечивают гибкость для компромиссов, таких как баланс между производительностью и использованием RAM. В результате оптимизации алгоритмов для Cardinal также включают выбор оптимальных рабочих точек в пространстве параметров.
Инженерные оптимизации
Хотя алгоритмы изначально проектируются с учетом абстрактных машин Тьюринга, реальная реализация сталкивается с такими проблемами, как сетевые задержки, ограничения облачных провайдеров на IOPS и ограничения оперативной памяти машины — ценного, но конечного ресурса.
Инженерные оптимизации обеспечивают практичность конвейера векторного поиска Cardinal и его соответствие ограничениям вычислительных ресурсов, оперативной памяти и других ресурсов. В разработке Cardinal мы сочетаем стандартные практики и инновационные техники. Такой подход позволяет компилятору C++ генерировать вычислительно оптимальный скомпилированный код, сохраняя при этом чистый, пригодный для бенчмаркинга и легко расширяемый исходный код, который облегчает быстрое добавление новых функций.
Вот несколько примеров инженерных практик, реализованных в Cardinal, демонстрирующих конкретные оптимизации:
Специализированные аллокаторы памяти и пулы памяти,
Корректно реализованный многопоточный код,
Иерархическая структура компонентов, облегчающая объединение элементов в различные конвейеры поиска,
Настройка кода для конкретных, критически важных сценариев использования.
Низкоуровневые оптимизации
Большая часть времени поиска тратится на относительно небольшие фрагменты кода, известные как ядра. Самый простой пример — ядро, вычисляющее расстояние L2 между двумя векторами.
Cardinal включает множество вычислительных ядер для различных целей, каждое из которых написано и оптимизировано специально для конкретной аппаратной платформы и сценария использования.
Cardinal поддерживает аппаратные платформы x86 и ARM, но другие платформы могут быть легко добавлены.
Для платформы x86 ядра Cardinal используют расширения AVX-512 F, CD, VL, BW, DQ, VPOPCNTDQ, VBMI, VBMI2, VNNI, BF16 и FP16. Также мы изучаем использование нового набора инструкций AMX.
Для платформы ARM ядра Cardinal доступны для наборов инструкций NEON и SVE.
Мы гарантируем, что Cardinal получает наиболее оптимальный код для вычислительных ядер. Мы не просто полагаемся на современный компилятор C++, который должен выполнить эту работу:
Мы используем специализированные инструменты, такие как Linux perf, для анализа горячих участков и метрик CPU
Мы используем инструменты анализа машинного кода, такие как GodBolt Compiler Explorer и uiCA, чтобы обеспечить оптимальное использование аппаратных «ресурсов», таких как количество обращений к RAM/кэшу, используемые инструкции CPU, регистры, вычислительные порты.
Мы используем итеративный подход, который чередует этапы проектирования, бенчмаркинга, профилирования и анализа ассемблерного кода.
Правильно оптимизированное вычислительное ядро может обеспечить ускорение в 2 или 3 раза по сравнению с наивным, но неоптимизированным ядром. Это может дополнительно привести к значению QPS в 2 раза выше или к снижению требований к памяти на облачной хост-машине на 20%.
AutoIndex: выбор стратегии поиска
Векторный поиск — это сложный процесс, включающий множество независимых компонентов, включая квантование, построение индекса, алгоритмы поиска, структуры данных и многое другое. Каждый компонент имеет множество настраиваемых параметров. Вместе они формируют весьма разнообразный спектр стратегий векторного поиска, а разные наборы данных и сценарии требуют разных стратегий поиска.
Чтобы лучше использовать потенциал повышения производительности, Cardinal, помимо поддержки нескольких стратегий в каждом компоненте, реализовал набор механизмов динамического выбора стратегии на основе AI, известных как AUTOINDEX. Он адаптивно выбирает наиболее подходящую стратегию на основе распределения заданного набора данных, предоставленного запроса и аппаратной конфигурации. Это помогает нам достигать оптимальной производительности, одновременно удовлетворяя требования пользователей к качеству поиска.
Бенчмарк Cardinal
Мы адаптировали ANN-benchmarks для поддержки Cardinal в нашей тестовой среде. ANN-benchmarks — это стандартный инструмент бенчмаркинга для оценки реализаций ANNS, который запускается на нескольких стандартных наборах данных, использующих разные метрики расстояния. Каждая оценка производительности проводится внутри docker-контейнера, ограниченного использованием одного потока. Метрики основаны на нескольких итерациях оценки, в которых используются многочисленные одиночные запросы. Результаты каждого оцениваемого фреймворка агрегируются в Pareto frontier recall-vs-QPS.
Все тесты выполнялись на машине того же типа, что и базовые ann-benchmarks (по состоянию на январь 2024 г.), а именно на машине Amazon EC2 r6i.16xlarge со следующей конфигурацией:
CPU: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
Количество ядер CPU: 32
Hyperthreading отключен
RAM: 512 GB
OS: Ubuntu 22.04.3 LTS с Linux kernel 6.2.0-1017-aws
Поддержка Huge pages не была включена.
Тесты запускались с опцией `--parallelism=31`.
Cardinal был скомпилирован с использованием компилятора clang 17.0.6.
Представленные ниже результаты бенчмарков относятся только к движку Cardinal и не включают дополнительные неиндексные оптимизации, предоставляемые Zilliz Cloud.
Примечание: Результаты, которые действительно включают оптимизации, специфичные для Zilliz Cloud, приведены выше, в начале статьи.
Следующие графики были получены путем взятия изображений графиков с результатами, представленными на странице ANN-benchmark в GitHub, и точного добавления поверх них дополнительной кривой Cardinal.
Для всех представленных бенчмарков Cardinal показывает очень конкурентоспособные результаты. И остается пространство для дальнейшего улучшения.
Что дальше?
Будущее, без сомнения, принесет нам новые вызовы. Разные требования, разные узкие места, более крупные наборы данных. Мы продолжаем работать над тем, чтобы сделать Cardinal еще лучше.
Путь освещен. Дорога ясна. Нам нужна лишь сила, чтобы следовать ей :)
Читать далее

Introducing Zilliz CLI and Agent Skills for Zilliz Cloud
Manage your vector database from your terminal or AI coding agent. Zilliz CLI and Agent Skills work with Claude Code, Cursor, Codex, and Copilot.

Zilliz Cloud Just Landed in Claude Code
The Zilliz Cloud Plugin brings the full power of Zilliz Cloud directly into your Claude Code terminal as natural-language conversations.

How to Build RAG with Milvus, QwQ-32B and Ollama
Hands-on tutorial on how to create a streamlined, powerful RAG pipeline that balances efficiency, accuracy, and scalability using the QwQ-32B and Milvus.



