Оптимизация векторных баз данных, улучшение генеративного ИИ на основе RAG
Это сообщение было первоначально опубликовано на канале Intel в Medium и публикуется здесь с разрешения.
Два метода оптимизации векторной базы данных при использовании RAG
Фотография Ильи Павлова на Unsplash
Кэти Чжан и доктор Малини Бхандару Соавторы: Линь Ян и Чангян Лю
Генеративные модели искусственного интеллекта (GenAI), которые находят все большее применение в нашей повседневной жизни, совершенствуются с помощью технологии генерации с расширением поиска (RAG), которая позволяет повысить точность и надежность ответа за счет получения фактов из внешних источников. RAG помогает обычной модели большого языка (LLM) понять контекст и уменьшить количество галлюцинаций за счет использования гигантской базы неструктурированных данных, хранящихся в виде векторов - математического представления, которое помогает передать контекст и взаимосвязи между данными.
RAG помогает извлекать больше контекстной информации и, следовательно, генерировать более качественные ответы, но векторные базы данных, на которые они опираются, становятся все больше и больше, чтобы обеспечить богатый контент для использования. Как на горизонте появляются LLM с триллионами параметров, так и векторные базы данных с миллиардами векторов не за горами. Как инженерам по оптимизации, нам было интересно узнать, сможем ли мы сделать векторные базы данных более производительными, быстрее загружать данные и быстрее создавать индексы, чтобы обеспечить скорость поиска даже при добавлении новых данных. Это не только сократит время ожидания пользователей, но и сделает ИИ-решения на базе RAG более устойчивыми.
В этой статье вы узнаете больше о векторных базах данных и их бенчмарках, наборах данных для изучения различных аспектов и инструментах, используемых для анализа производительности, - обо всем, что необходимо для начала оптимизации векторных баз данных. Мы также поделимся нашими достижениями в оптимизации двух популярных решений для векторных баз данных, чтобы вдохновить вас на путь оптимизации производительности и воздействия на устойчивость.
Понимание векторных баз данных
В отличие от традиционных реляционных или нереляционных баз данных, где данные хранятся в структурированном виде, векторная база данных содержит математическое представление отдельных элементов данных, называемое вектором, построенное с помощью функции встраивания или преобразования. Вектор обычно представляет особенности или семантические значения и может быть коротким или длинным. Векторные базы данных выполняют поиск векторов по сходству с помощью метрики расстояния (где "ближе" означает, что результаты более похожи), такой как евклидово, точечное или косинусное сходство.
Чтобы ускорить процесс поиска, векторные данные организуются с помощью механизма индексирования. Примерами таких методов организации являются плоские структуры, инвертированный файл (IVF), иерархические перемещаемые малые миры (HNSW), хеширование с учетом локальности (LSH) и другие. Каждый из этих методов способствует повышению эффективности и результативности поиска похожих векторов в случае необходимости.
Давайте рассмотрим, как можно использовать базу данных векторов в системе GenAI. Рисунок 1 иллюстрирует как загрузку данных в векторную базу, так и ее использование в контексте приложения GenAI. Когда вы вводите подсказку, она подвергается процессу преобразования, идентичному тому, который используется для создания векторов в базе данных. Затем эта преобразованная векторная подсказка используется для извлечения похожих векторов из базы данных векторов. Эти извлеченные элементы, по сути, служат разговорной памятью, предоставляя контекстную историю для подсказок, подобно тому, как работают LLM. Эта функция особенно полезна в обработке естественного языка, компьютерном зрении, рекомендательных системах и других областях, требующих семантического понимания и сопоставления данных. Ваша первоначальная подсказка впоследствии "объединяется" с извлеченными элементами, обеспечивая контекст и помогая LLM формулировать ответы на основе предоставленного контекста, а не только полагаться на свои исходные обучающие данные.
Рисунок 1. Архитектура приложения RAG.
Векторы хранятся и индексируются для быстрого поиска. Векторные базы данных бывают двух видов: традиционные базы данных, которые были расширены для хранения векторов, и специально созданные векторные базы данных. Примерами традиционных баз данных, поддерживающих векторы, являются Redis, pgvector, Elasticsearch и OpenSearch. Примерами специально созданных векторных баз данных являются проприетарные решения Zilliz и Pinecone, а также проекты с открытым исходным кодом Milvus, Weaviate, Qdrant, Faiss и Chroma. Вы можете узнать больше о векторных базах данных на GitHub через LangChain и OpenAI Cookbook.
Мы рассмотрим по одной базе данных из каждой категории - Milvus и Redis.
Повышение производительности
Прежде чем перейти к оптимизации, давайте рассмотрим, как оцениваются векторные базы данных, некоторые механизмы оценки и доступные инструменты анализа производительности.
Метрики производительности
Давайте рассмотрим ключевые метрики, которые помогут вам оценить производительность векторных баз данных.
- Задержка загрузки измеряет время, необходимое для загрузки данных в память векторной базы данных и создания индекса. Индекс - это структура данных, используемая для эффективной организации и извлечения векторных данных на основе их сходства или расстояния. Типы индексов in-memory включают плоский индекс, IVF_FLAT, IVF_PQ, HNSW, масштабируемые ближайшие соседи (ScaNN)и DiskANN.
- Recall - это доля истинных совпадений, или релевантных элементов, найденных в K лучших результатах, полученных поисковым алгоритмом. Более высокие значения показателя Recall указывают на лучший поиск релевантных элементов.
- Количество запросов в секунду (QPS) - это скорость, с которой векторная база данных может обрабатывать входящие запросы. Более высокие значения QPS означают лучшую способность обработки запросов и пропускную способность системы.
Бенчмаркинг фреймворков
Рисунок 2. Схема бенчмаркинга векторных баз данных.
Для проведения бенчмаркинга векторной базы данных требуется сервер векторной базы данных и клиенты. В наших тестах производительности мы использовали два популярных инструмента с открытым исходным кодом.
- VectorDBBench: Разработанный и открытый компанией Zilliz, VectorDBBench помогает тестировать различные векторные базы данных с разными типами индексов и предоставляет удобный веб-интерфейс.
- vector-db-benchmark: Разработанный и открытый компанией Qdrant, vector-db-benchmark помогает протестировать несколько типичных векторных баз данных для типа индекса HNSW. Он запускает тесты через командную строку и предоставляет __файл Docker Compose для упрощения запуска серверных компонентов.
Рисунок 3. Пример команды vector-db-benchmark, используемой для запуска эталонного теста.
Но эталонный фреймворк - это только часть уравнения. Нам нужны данные, которые позволят проверить различные аспекты самого решения векторной базы данных, такие как способность обрабатывать большие объемы данных, различные размеры векторов и скорость поиска.
Открытые наборы данных для тестирования векторных баз данных
Большие наборы данных - хорошие кандидаты для тестирования задержки нагрузки и распределения ресурсов. Некоторые наборы данных имеют высокую размерность и хорошо подходят для тестирования скорости вычисления сходства.
Размерность наборов данных варьируется от 25 до 2048. Набор данных LAION, открытая коллекция изображений, использовался для обучения очень больших визуальных и языковых глубоко нейронных моделей, таких как стабильные диффузионные генеративные модели. Набор данных OpenAI из 5 миллионов векторов, каждый из которых имеет размерность 1536, был создан VectorDBBench путем запуска OpenAI на необработанных данных. Учитывая, что каждый элемент вектора имеет тип FLOAT, для сохранения одних только векторов требуется около 29 ГБ (5M * 1536 * 4) памяти, плюс еще столько же для хранения индексов и других метаданных - итого 58 ГБ памяти для тестирования. При использовании инструмента vector-db-benchmark обеспечьте достаточное дисковое пространство для сохранения результатов.
Для тестирования задержки загрузки нам нужна большая коллекция векторов, которую предоставляет deep-image-96-angular. Для проверки производительности генерации индексов и вычисления сходства векторы высокой размерности дают большую нагрузку. Для этого мы выбрали набор данных 500K с векторами размерности 1536.
Инструменты для проверки производительности
Мы рассмотрели способы нагрузить систему, чтобы выявить интересующие нас метрики, но давайте изучим, что происходит на более низком уровне: насколько загружен вычислительный блок, потребление памяти, ожидание блокировок и т. д.? Эти данные дают представление о поведении базы данных, что особенно полезно для выявления проблемных областей.
Утилита top в Linux предоставляет информацию о производительности системы. Однако инструмент perf в Linux позволяет получить более глубокие сведения. Чтобы узнать больше, мы также рекомендуем ознакомиться с примерами Linux perf и методом анализа микроархитектуры Intel "сверху вниз". Еще один инструмент - Intel® vTune™ Profiler, который полезен при оптимизации производительности и конфигурации не только приложений, но и системы для различных рабочих нагрузок, включая HPC, облачные вычисления, IoT, медиа, системы хранения данных и многое другое.
Оптимизации базы данных Milvus Vector
Давайте рассмотрим несколько примеров того, как мы пытались повысить производительность векторной базы данных Milvus.
Сокращение накладных расходов на перемещение памяти при записи в буфер датанода
Прокси-серверы Milvus записывают данные в лог-брокер через MsgStream. Затем узлы данных потребляют эти данные, преобразуя и сохраняя их в сегменты. Сегменты объединяют вновь вставленные данные. Логика слияния выделяет новый буфер для хранения/перемещения старых и новых вставляемых данных, а затем возвращает новый буфер в качестве старых данных для следующего слияния данных. В результате старые данные становятся все больше и больше, что, в свою очередь, замедляет перемещение данных. Профили производительности показали высокие накладные расходы на эту логику.
Рисунок 4. Слияние и перемещение данных в векторной базе данных приводит к высокой производительности.
Мы изменили логику работы буфера слияния, чтобы напрямую добавлять новые данные к старым, избегая выделения нового буфера и перемещения больших старых данных. Перфопрофили подтверждают отсутствие накладных расходов на эту логику. Метрики микрокода metric_CPU operating frequency и metric_CPU utilization указывают на улучшение, которое согласуется с тем, что системе больше не нужно ждать долгого перемещения памяти. Задержка загрузки улучшилась более чем на 60 %. Улучшение зафиксировано на GitHub.
Рисунок 5. При меньшем копировании мы видим улучшение производительности более чем на 50 % в задержке загрузки.
Инвертированное построение индексов с уменьшенной нагрузкой на выделение памяти
Поисковая система Knowhere компании Milvus использует алгоритм Elkan k-means для обучения кластерных данных для создания инвертированных файловых (IVF) индексов. Каждый раунд обучения данных определяет количество итераций. Чем больше счетчик, тем лучше результаты обучения. Однако это также означает, что алгоритм Элкана будет вызываться чаще.
Алгоритм Elkan при каждом выполнении обрабатывает выделение и удаление памяти. В частности, он выделяет память для хранения половины размера данных симметричной матрицы, исключая диагональные элементы. В Knowhere размерность симметричной матрицы, используемой алгоритмом Elkan, установлена на 1024, что приводит к размеру памяти около 2 МБ. Это означает, что для каждого раунда обучения Elkan многократно выделяет и деаллоцирует 2 МБ памяти.
Данные профилирования указывали на частую активность выделения большого объема памяти. Фактически, это вызывало выделение виртуальной области памяти (VMA), выделение физических страниц, настройку карты страниц и обновление статистики cgroup памяти в ядре. Такая активность выделения/деаллокации большого объема памяти в некоторых ситуациях может также усугубить фрагментацию памяти. Это существенный налог.
Структура IndexFlatElkan специально разработана и создана для поддержки алгоритма Элкана. В каждом процессе обучения данных инициализируется экземпляр IndexFlatElkan. Чтобы уменьшить влияние на производительность, возникающее из-за частого выделения и удаления памяти в алгоритме Elkan, мы рефакторизовали логику кода, перенеся управление памятью за пределы функции алгоритма Elkan в процесс построения IndexFlatElkan. Это позволяет выделять память только один раз на этапе инициализации, обслуживая все последующие вызовы функции алгоритма Elkan из текущего процесса обучения данным, и помогает улучшить задержку загрузки примерно на 3 %. Найти патч Knowhere можно здесь.
Ускорение векторного поиска в Redis с помощью программной предвыборки
Redis, популярное традиционное хранилище данных в памяти с ключами-значениями, недавно начало поддерживать векторный поиск. Чтобы выйти за рамки обычного хранилища ключевых значений, он предлагает модули расширения; модуль RediSearch облегчает хранение и поиск векторов непосредственно в Redis.
Для поиска векторного сходства Redis поддерживает два алгоритма, а именно грубую силу и HNSW. Алгоритм HNSW специально разработан для эффективного поиска приблизительных ближайших соседей в высокоразмерных пространствах. Он использует приоритетную очередь с именем candidate_set для управления всеми векторами-кандидатами для вычисления расстояния.
Каждый вектор-кандидат содержит значительные метаданные в дополнение к данным вектора. В результате при загрузке кандидата из памяти он может вызывать пропуски кэша данных, что приводит к задержкам в обработке. Наша оптимизация вводит программную предварительную выборку, чтобы проактивно загружать следующего кандидата во время обработки текущего. Это усовершенствование позволило повысить производительность на 2-3 % при векторном поиске сходства в одном экземпляре Redis. Патч находится в процессе апстриминга.
Изменение поведения GCC по умолчанию для предотвращения штрафов за смешанный ассемблерный код
Для достижения максимальной производительности часто используемые участки кода часто пишутся на ассемблере вручную. Однако, когда разные сегменты кода написаны разными людьми или в разное время, используемые инструкции могут быть из несовместимых наборов инструкций ассемблера, таких как Intel® Advanced Vector Extensions 512 (Intel® AVX-512) и Streaming SIMD Extensions (SSE). Если смешанный код не скомпилировать должным образом, он приведет к снижению производительности. Подробнее о смешивании инструкций Intel AVX и SSE можно узнать здесь.
Вы можете легко определить, используете ли вы смешанный режим ассемблера и не скомпилировали ли вы код с VZEROUPPER, что приводит к снижению производительности. Это можно заметить с помощью команды perf, например sudo perf stat -e 'assists.sse_avx_mix/event/event=0xc1,umask=0x10/' <workload>. Если в вашей ОС нет поддержки этого события, используйте cpu/event=0xc1,umask=0x10,name=assists_sse_avx_mix/.
Компилятор Clang по умолчанию вставляет VZEROUPPER, что позволяет избежать штрафа за смешанный режим. Но компилятор GCC вставляет VZEROUPPER только в том случае, если указаны флаги компилятора -O2 или -O3. Мы связались с командой GCC и объяснили проблему, и теперь по умолчанию они корректно обрабатывают ассемблерный код в смешанном режиме.
Начните оптимизировать свои векторные базы данных
Векторные базы данных играют неотъемлемую роль в GenAI, и они становятся все больше и больше, чтобы генерировать более качественные ответы. Что касается оптимизации, то приложения ИИ ничем не отличаются от других программных приложений, поскольку они раскрывают свои секреты при использовании стандартных инструментов анализа производительности, а также бенчмарков и стресс-факторов.
Используя эти инструменты, мы обнаружили ловушки производительности, связанные с излишним выделением памяти, неспособностью выполнять предварительную выборку инструкций и использованием неправильных опций компилятора. Основываясь на полученных результатах, мы внесли улучшения в Milvus, Knowhere, Redis и компилятор GCC, чтобы сделать ИИ немного более производительным и устойчивым. Векторные базы данных - важный класс приложений, достойный ваших усилий по оптимизации. Мы надеемся, что эта статья поможет вам начать работу.
- Понимание векторных баз данных
- Повышение производительности
- Оптимизации базы данных Milvus Vector
- Ускорение векторного поиска в Redis с помощью программной предвыборки
- Изменение поведения GCC по умолчанию для предотвращения штрафов за смешанный ассемблерный код
- Начните оптимизировать свои векторные базы данных
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