O que permite a pesquisa por semelhança na base de dados vetorial Milvus?
imagem de capa
Este artigo foi escrito por Yudong Cai e traduzido por Angela Ni.
Sendo o motor de execução vetorial principal, o Knowhere para o Milvus é o que um motor é para um carro desportivo. Esta publicação apresenta o que é o Knowhere, como é diferente do Faiss e como o código do Knowhere está estruturado.
Saltar para:
- O conceito de Knowhere
- Knowhere na arquitetura Milvus
- Knowhere vs Faiss
- Compreender o código do Knowhere
- Adicionando índices ao Knowhere
O conceito de Knowhere
Em termos gerais, o Knowhere é uma interface de operação para aceder a serviços nas camadas superiores do sistema e a bibliotecas de pesquisa de semelhanças vectoriais como o Faiss, o Hnswlib e o Annoy nas camadas inferiores do sistema. Além disso, o Knowhere é também responsável pela computação heterogénea. Mais concretamente, o Knowhere controla em que hardware (por exemplo, CPU ou GPU) executar a criação de índices e os pedidos de pesquisa. É assim que o Knowhere recebe o seu nome - saber onde executar as operações. Mais tipos de hardware, incluindo DPU e TPU, serão suportados em versões futuras.
Num sentido mais lato, o Knowhere também incorpora outras bibliotecas de índices de terceiros, como a Faiss. Por conseguinte, no seu conjunto, o Knowhere é reconhecido como o principal motor de cálculo vetorial da base de dados vetorial Milvus.
A partir do conceito de Knowhere, podemos ver que este apenas processa tarefas de computação de dados, enquanto tarefas como a fragmentação, o equilíbrio de carga e a recuperação de desastres estão fora do âmbito de trabalho do Knowhere.
A partir do Milvus 2.0.1, o Knowhere (no sentido mais lato) torna-se independente do projeto Milvus.
Knowhere na arquitetura Milvus
arquitetura knowhere
A computação em Milvus envolve principalmente operações vectoriais e escalares. A Knowhere apenas trata das operações sobre vectores em Milvus. A figura acima ilustra a arquitetura Knowhere em Milvus.
A camada mais baixa é o hardware do sistema. As bibliotecas de índice de terceiros estão na parte superior do hardware. Em seguida, o Knowhere interage com o nó de índice e o nó de consulta na parte superior através do CGO.
Este artigo fala sobre o Knowhere no seu sentido mais lato, conforme assinalado na moldura azul da ilustração da arquitetura.
Knowhere Vs Faiss
O Knowhere não só alarga as funções do Faiss como também optimiza o desempenho. Mais especificamente, o Knowhere tem as seguintes vantagens
1. Suporte para BitsetView
Inicialmente, o bitset foi introduzido no Milvus para efeitos de "eliminação suave". Um vetor apagado suavemente continua a existir na base de dados, mas não será computado durante uma pesquisa ou consulta de semelhança de vectores. Cada bit no conjunto de bits corresponde a um vetor indexado. Se um vetor estiver marcado como "1" no conjunto de bits, significa que esse vetor foi eliminado de forma suave e não será envolvido durante uma pesquisa de vectores.
Os parâmetros do conjunto de bits são adicionados a todas as APIs de consulta de índice Faiss expostas no Knowhere, incluindo índices de CPU e GPU.
Saiba mais sobre como o bitset permite a versatilidade da pesquisa vetorial.
2. Suporte a mais métricas de similaridade para indexação de vetores binários
Além de Hamming, o Knowhere também oferece suporte a Jaccard, Tanimoto, Superestrutura e Subestrutura. O Jaccard e o Tanimoto podem ser utilizados para medir a semelhança entre dois conjuntos de amostras, enquanto o Superstructure e o Substructure podem ser utilizados para medir a semelhança de estruturas químicas.
3. Suporte do conjunto de instruções AVX512
O próprio Faiss suporta vários conjuntos de instruções, incluindo AArch64, SSE4.2 e AVX2. O Knowhere alarga ainda mais os conjuntos de instruções suportados, acrescentando o AVX512, que pode melhorar o desempenho da construção e consulta de índices em 20% a 30% em comparação com o AVX2.
4. Seleção automática de instruções SIMD
O Knowhere foi projetado para funcionar bem em um amplo espetro de processadores de CPU (plataformas locais e em nuvem) com diferentes instruções SIMD (por exemplo, SIMD SSE, AVX, AVX2 e AVX512). Assim, o desafio é, dado um único pedaço de binário de software (ou seja, Milvus), como fazer com que ele invoque automaticamente as instruções SIMD adequadas em qualquer processador de CPU? O Faiss não suporta a seleção automática de instruções SIMD e os utilizadores têm de especificar manualmente o sinalizador SIMD (por exemplo, "-msse4") durante a compilação. No entanto, o Knowhere é construído através da refacção da base de código do Faiss. As funções comuns (por exemplo, cálculo de semelhanças) que dependem de acelerações SIMD são eliminadas. Em seguida, para cada função, são implementadas quatro versões (ou seja, SSE, AVX, AVX2, AVX512) e cada uma é colocada num ficheiro fonte separado. Em seguida, os ficheiros de origem são compilados individualmente com o sinalizador SIMD correspondente. Por conseguinte, em tempo de execução, o Knowhere pode escolher automaticamente as instruções SIMD mais adequadas com base nas bandeiras actuais da CPU e ligar os ponteiros de função corretos utilizando o hooking.
5. Outras optimizações de desempenho
Leia Milvus: um sistema de gerenciamento de dados vetoriais criado para fins específicos para obter mais informações sobre a otimização de desempenho do Knowhere.
Entendendo o código Knowhere
Conforme mencionado na primeira seção, o Knowhere lida apenas com operações de pesquisa vetorial. Portanto, o Knowhere processa apenas o campo vetorial de uma entidade (atualmente, é suportado apenas um campo vetorial para entidades em uma coleção). A construção de índices e a pesquisa de semelhança de vectores também são direcionadas para o campo vetorial de um segmento. Para compreender melhor o modelo de dados, leia o blogue aqui.
campos de entidade
Índice
O índice é um tipo de estrutura de dados independente dos dados vectoriais originais. A indexação requer quatro etapas: criar um índice, treinar dados, inserir dados e construir um índice.
Para algumas das aplicações de IA, a formação do conjunto de dados é um processo individual da pesquisa de vectores. Neste tipo de aplicação, os dados dos conjuntos de dados são primeiro treinados e depois inseridos numa base de dados vetorial como o Milvus para pesquisa de semelhanças. Conjuntos de dados abertos como o sift1M e o sift1B fornecem dados para treino e teste. No entanto, no Knowhere, os dados para treino e pesquisa são misturados. Ou seja, o Knowhere treina todos os dados de um segmento e, em seguida, insere todos os dados treinados e cria um índice para eles.
Estrutura de código do Knowhere
DataObj é a classe base de toda a estrutura de dados no Knowhere. Size()
é o único método virtual em DataObj. A classe Index herda de DataObj com um campo chamado "size_". A classe Index também tem dois métodos virtuais - Serialize()
e Load()
. A classe VecIndex derivada de Index é a classe base virtual para todos os índices vectoriais. VecIndex fornece métodos que incluem Train()
, Query()
, GetStatistics()
, e ClearStatistics()
.
classe de base
Outros tipos de índices estão listados à direita na figura acima.
- O índice Faiss tem duas subclasses: FaissBaseIndex, para todos os índices em vectores de ponto flutuante, e FaissBaseBinaryIndex, para todos os índices em vectores binários.
- GPUIndex é a classe base para todos os índices Faiss GPU.
- OffsetBaseIndex é a classe de base para todos os índices desenvolvidos pelo próprio utilizador. Apenas o ID do vetor é armazenado no ficheiro de índice. Como resultado, o tamanho de um ficheiro de índice para vectores de 128 dimensões pode ser reduzido em 2 ordens de grandeza. Recomendamos que os vectores originais também sejam tidos em consideração quando se utiliza este tipo de índice para a pesquisa de semelhança de vectores.
IDMAP
Tecnicamente falando, o IDMAP não é um índice, mas sim utilizado para pesquisa de força bruta. Quando os vectores são inseridos na base de dados de vectores, não é necessário treinar os dados nem criar um índice. As pesquisas serão realizadas diretamente nos dados vectoriais inseridos.
No entanto, por uma questão de coerência do código, o IDMAP também herda a classe VecIndex com todas as suas interfaces virtuais. A utilização do IDMAP é idêntica à dos outros índices.
IVF
Os índices IVF (inverted file) são os mais frequentemente utilizados. A classe IVF é derivada de VecIndex e FaissBaseIndex, e estende-se ainda a IVFSQ e IVFPQ. GPUIVF é derivada de GPUndex e IVF. Em seguida, GPUIVF estende-se ainda a GPUIVFSQ e GPUIVFPQ.
IVFSQHybrid é uma classe para índice híbrido auto-desenvolvido que é executado por quantização grosseira na GPU. E a pesquisa no balde é executada na CPU. Este tipo de índice pode reduzir a ocorrência de cópia de memória entre CPU e GPU, aproveitando o poder de computação da GPU. O IVFSQHybrid tem a mesma taxa de recuperação que o GPUIVFSQ, mas apresenta um melhor desempenho.
A estrutura da classe de base para índices binários é relativamente mais simples. BinaryIDMAP e BinaryIVF são derivados de FaissBaseBinaryIndex e VecIndex.
índice de terceiros
Atualmente, apenas são suportados dois tipos de índices de terceiros para além do Faiss: o índice baseado em árvores Annoy e o índice baseado em gráficos HNSW. Estes dois índices de terceiros comuns e frequentemente utilizados são ambos derivados do VecIndex.
Adicionar índices ao Knowhere
Se pretender adicionar novos índices ao Knowhere, pode consultar primeiro os índices existentes:
- Para adicionar um índice baseado em quantização, consulte IVF_FLAT.
- Para adicionar um índice baseado em gráficos, consulte HNSW.
- Para adicionar um índice baseado em árvore, consulte Annoy.
Depois de consultar o índice existente, pode seguir os passos abaixo para adicionar um novo índice ao Knowhere.
- Adicione o nome do novo índice em
IndexEnum
. O tipo de dados é string. - Adicione uma verificação de validação de dados ao novo índice no ficheiro
ConfAdapter.cpp
. A verificação de validação destina-se principalmente a validar os parâmetros de formação e consulta de dados. - Crie um novo ficheiro para o novo índice. A classe de base do novo índice deve incluir
VecIndex
, e a interface virtual necessária deVecIndex
. - Adicione a lógica de construção do índice para o novo índice em
VecIndexFactory::CreateVecIndex()
. - Adicione o teste de unidade no diretório
unittest
.
Sobre a série Deep Dive
Com o anúncio oficial da disponibilidade geral do Milvus 2.0, orquestrámos esta série de blogues Milvus Deep Dive para fornecer uma interpretação aprofundada da arquitetura e do código-fonte do Milvus. Os tópicos abordados nesta série de blogues incluem:
- O conceito de Knowhere
- Knowhere na arquitetura Milvus
- Knowhere Vs Faiss
- Entendendo o código Knowhere
- Adicionar índices ao Knowhere
- Sobre a série 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