Knowhere
В этой теме рассказывается о Knowhere, основном механизме векторного исполнения Milvus.
Обзор
Knowhere - это основной механизм выполнения векторов в Milvus, который включает в себя несколько библиотек поиска векторного сходства, включая Faiss, Hnswlib и Annoy. Knowhere также разработан для поддержки гетерогенных вычислений. Она контролирует, на каком оборудовании (CPU или GPU) выполнять запросы на создание индекса и поиск. Именно так Knowhere получила свое название - знание того, где выполнять операции. В будущих релизах будут поддерживаться другие типы оборудования, включая DPU и TPU.
Knowhere в архитектуре Milvus
На рисунке ниже показано место Knowhere в архитектуре Milvus.
Knowhere
Самый нижний слой - это системное оборудование. Над ним располагаются сторонние индексные библиотеки. На верхнем уровне Knowhere взаимодействует с индексным узлом и узлом запросов через CGO, что позволяет пакетам Go вызывать код на C.
Преимущества Knowhere
Ниже перечислены преимущества Knowhere по сравнению с Faiss.
Поддержка BitsetView
Milvus вводит механизм битов для реализации "мягкого удаления". Мягко удаленный вектор все еще существует в базе данных, но не будет вычислен при поиске или запросе векторного сходства.
Каждый бит в битовом наборе соответствует индексированному вектору. Если в наборе битов вектор помечен как "1", это означает, что данный вектор мягко удален и не будет задействован в векторном поиске. Параметр bitset применяется ко всем API запросов индекса Фейса в Knowhere, включая индексы CPU и GPU.
Более подробную информацию о механизме bitset можно найти в разделе bitset.
Поддержка нескольких метрик сходства для индексирования бинарных векторов
Knowhere поддерживает Hamming, Jaccard, Tanimoto, Superstructure и Substructure. Жаккард и Танимото могут использоваться для измерения сходства между двумя наборами образцов, а Superstructure и Substructure - для измерения сходства химических структур.
Поддержка набора инструкций AVX512
Помимо AArch64, SSE4.2 и AVX2, наборов инструкций, уже поддерживаемых Faiss, Knowhere также поддерживает AVX512, который может повысить производительность построения индексов и запросов на 20-30 % по сравнению с AVX2.
Автоматический выбор SIMD-инструкций
Knowhere поддерживает автоматический вызов подходящих SIMD-инструкций (например, SIMD SSE, AVX, AVX2 и AVX512) на любом процессоре (как на локальных, так и на облачных платформах), так что пользователям не нужно вручную указывать флаг SIMD (например, "-msse4") во время компиляции.
Knowhere создается путем рефакторинга кодовой базы Faiss. Общие функции (например, вычисление подобия), которые зависят от ускорения SIMD, вырезаются из кода. Затем для каждой функции реализуются четыре версии (т. е. SSE, AVX, AVX2, AVX512), каждая из которых помещается в отдельный исходный файл. Затем исходные файлы компилируются по отдельности с соответствующим флагом SIMD. Таким образом, во время выполнения Knowhere может автоматически выбирать наиболее подходящие SIMD-инструкции, основываясь на текущих флагах процессора, а затем связывать нужные указатели функций с помощью хуков.
Другие оптимизации производительности
Подробнее об оптимизации производительности Knowhere читайте в статье Milvus: A Purpose-Built Vector Data Management System.
Структура кода Knowhere
Вычисления в Milvus в основном включают в себя векторные и скалярные операции. Knowhere обрабатывает только операции по индексированию векторов.
Индекс - это структура данных, независимая от исходных векторных данных. Как правило, индексирование требует четырех шагов: создание индекса, обучение данных, вставка данных и построение индекса. В некоторых приложениях ИИ обучение наборов данных отделено от поиска векторов. Данные из наборов данных сначала обучаются, а затем вставляются в векторную базу данных, например Milvus, для поиска сходства. Например, в открытых наборах данных sift1M и sift1B различаются данные для обучения и данные для тестирования.
Однако в Knowhere данные для обучения и для поиска одинаковы. Knowhere обучает все данные в сегменте, а затем вставляет все обученные данные и строит для них индекс.
DataObj
: базовый класс
DataObj
является базовым классом всех структур данных в Knowhere. Size()
- единственный виртуальный метод в DataObj
. Класс Index наследуется от DataObj
с полем "size_". Класс Index также имеет два виртуальных метода - Serialize()
и Load()
. Класс VecIndex
, производный от Index
, является виртуальным базовым классом для всех векторных индексов. VecIndex
предоставляет методы, включая Train()
, Query()
, GetStatistics()
и ClearStatistics()
.
базовый класс
Некоторые другие типы индексов перечислены справа на рисунке выше.
Индекс Фейса имеет два базовых класса:
FaissBaseIndex
для всех индексов векторов с плавающей точкой иFaissBaseBinaryIndex
для всех индексов двоичных векторов.GPUIndex
является базовым классом для всех индексов Фейса GPU.OffsetBaseIndex
базовый класс для всех индексов собственной разработки. Учитывая, что в индексном файле хранятся только идентификаторы векторов, размер файла для 128-мерных векторов может быть уменьшен на 2 порядка.
IDMAP
: грубый поиск
IDMAP
Технически говоря, IDMAP
не является индексом, а скорее используется для поиска методом перебора. При вводе векторов в базу данных не требуется ни обучения данных, ни построения индекса. Поиск будет осуществляться непосредственно по вставленным векторным данным.
Однако для согласованности кода IDMAP
также наследует от класса VecIndex
со всеми его виртуальными интерфейсами. Использование IDMAP
такое же, как и других индексов.
ЭКО-индексы
IVF
Индексы IVF (инвертированный файл) являются наиболее часто используемыми. Класс IVF
является производным от VecIndex
и FaissBaseIndex
, далее расширяется до IVFSQ
и IVFPQ
. GPUIVF
является производным от GPUIndex
и IVF
. Затем GPUIVF
расширяется до GPUIVFSQ
и GPUIVFPQ
.
IVFSQHybrid
является самостоятельно разработанным гибридным индексом. Грубый квантователь выполняется на GPU, а поиск в ведре - на CPU. Этот тип индекса позволяет уменьшить количество копий памяти между CPU и GPU, используя вычислительную мощность GPU. IVFSQHybrid
имеет тот же коэффициент отзыва, что и GPUIVFSQ
, но обладает лучшей производительностью.
Структура базового класса для бинарных индексов относительно проще. BinaryIDMAP
и BinaryIVF
являются производными от FaissBaseBinaryIndex
и VecIndex
.
Сторонние индексы
Сторонние индексы
В настоящее время, помимо Faiss, поддерживаются только два типа сторонних индексов: древовидный Annoy
и графовый HNSW
. Эти два распространенных и часто используемых сторонних индекса получены из VecIndex
.
Добавление индексов в Knowhere
Если вы хотите добавить новые индексы в Knowhere, сначала вы можете обратиться к существующим индексам:
Чтобы добавить индексы, основанные на квантовании, обратитесь к
IVF_FLAT
.Чтобы добавить индексы на основе графов, обратитесь к
HNSW
.Чтобы добавить индексы на основе деревьев, обратитесь к
Annoy
.
После обращения к существующему индексу вы можете выполнить следующие шаги, чтобы добавить новый индекс в Knowhere.
Добавьте имя нового индекса в поле
IndexEnum
. Тип данных - строка.Добавьте проверку достоверности данных для нового индекса в файл
ConfAdapter.cpp
. Проверка валидности нужна в основном для проверки параметров подготовки данных и запроса.Создайте новый файл для нового индекса. Базовый класс нового индекса должен включать
VecIndex
, а также необходимый виртуальный интерфейсVecIndex
.Добавьте логику построения индекса для нового индекса в
VecIndexFactory::CreateVecIndex()
.Добавьте юнит-тест в каталог
unittest
.
Что дальше
После изучения того, как Knowhere работает в Milvus, вы также можете захотеть:
Узнать о различных типах индексов, которые поддерживает Milvus.
Узнать о механизме битовых наборов.
Понять , как обрабатываются данные в Milvus.