🚀 Essayez Zilliz Cloud, la version entièrement gérée de Milvus, gratuitement—découvrez des performances 10x plus rapides ! Essayez maintenant>>

milvus-logo
LFAI
  • Home
  • Blog
  • Quelle est la puissance de la recherche de similarité dans la base de données vectorielle Milvus ?

Quelle est la puissance de la recherche de similarité dans la base de données vectorielle Milvus ?

  • Engineering
May 10, 2022
Yudong Cai

cover image Image de couverture

Cet article a été rédigé par Yudong Cai et traduit par Angela Ni.

En tant que moteur d'exécution vectorielle, Knowhere est à Milvus ce qu'un moteur est à une voiture de sport. Cet article présente ce qu'est Knowhere, en quoi il est différent de Faiss, et comment le code de Knowhere est structuré.

Aller à :

Le concept de Knowhere

Au sens strict, Knowhere est une interface d'exploitation permettant d'accéder à des services dans les couches supérieures du système et à des bibliothèques de recherche de similarités vectorielles telles que Faiss, Hnswlib, Annoy dans les couches inférieures du système. En outre, Knowhere est également responsable de l'informatique hétérogène. Plus précisément, Knowhere contrôle sur quel matériel (par exemple, CPU ou GPU) sont exécutées les requêtes de construction d'index et de recherche. C'est ainsi que Knowhere tire son nom - savoir où exécuter les opérations. D'autres types de matériel, notamment les DPU et TPU, seront pris en charge dans les prochaines versions.

Dans un sens plus large, Knowhere intègre également d'autres bibliothèques d'indexation tierces comme Faiss. Par conséquent, dans son ensemble, Knowhere est reconnu comme le moteur principal de calcul vectoriel dans la base de données vectorielles Milvus.

Le concept de Knowhere montre qu'il ne traite que les tâches de calcul des données, alors que les tâches telles que le partage, l'équilibre des charges et la reprise après sinistre dépassent le champ d'action de Knowhere.

À partir de Milvus 2.0.1, Knowhere (au sens large) devient indépendant du projet Milvus.

Knowhere dans l'architecture Milvus

knowhere architecture architecture de knowhere

Le calcul dans Milvus implique principalement des opérations vectorielles et scalaires. Knowhere ne gère que les opérations sur les vecteurs dans Milvus. La figure ci-dessus illustre l'architecture de Knowhere dans Milvus.

La couche inférieure est le matériel du système. Les bibliothèques d'indexation tierces se trouvent au-dessus du matériel. Knowhere interagit ensuite avec le nœud d'index et le nœud de requête au sommet via CGO.

Cet article parle de Knowhere dans son sens le plus large, comme indiqué dans le cadre bleu de l'illustration de l'architecture.

Knowhere vs Faiss

Knowhere ne se contente pas d'étendre les fonctions de Faiss, il en optimise également les performances. Plus précisément, Knowhere présente les avantages suivants.

1. Prise en charge de BitsetView

Initialement, les bitset ont été introduits dans Milvus dans le but de procéder à une "suppression douce". Un vecteur supprimé en douceur existe toujours dans la base de données mais ne sera pas calculé lors d'une recherche ou d'une requête de similarité vectorielle. Chaque bit de l'ensemble de bits correspond à un vecteur indexé. Si un vecteur est marqué "1" dans l'ensemble de bits, cela signifie que ce vecteur est supprimé et qu'il ne sera pas pris en compte lors d'une recherche de vecteurs.

Les paramètres de bitset sont ajoutés à toutes les API de requête d'index Faiss exposées dans Knowhere, y compris les index CPU et GPU.

En savoir plus sur la façon dont les bitset permettent la polyvalence de la recherche vectorielle.

2. Prise en charge d'autres mesures de similarité pour l'indexation de vecteurs binaires

Outre Hamming, Knowhere supporte également Jaccard, Tanimoto, Superstructure, Substructure. Jaccard et Tanimoto peuvent être utilisés pour mesurer la similarité entre deux ensembles d'échantillons, tandis que Superstructure et Substructure peuvent être utilisés pour mesurer la similarité des structures chimiques.

3. Prise en charge du jeu d'instructions AVX512

Faiss lui-même prend en charge plusieurs jeux d'instructions, notamment AArch64, SSE4.2, AVX2. Knowhere étend encore les jeux d'instructions pris en charge en ajoutant AVX512, qui peut améliorer les performances de la construction d'index et des requêtes de 20 à 30 % par rapport à AVX2.

4. Sélection automatique des instructions SIMD

Knowhere est conçu pour fonctionner correctement sur un large spectre de processeurs CPU (à la fois sur site et sur des plateformes cloud) avec différentes instructions SIMD (par exemple, SIMD SSE, AVX, AVX2, et AVX512). Le défi est donc le suivant : étant donné un binaire logiciel unique (c'est-à-dire Milvus), comment faire en sorte qu'il invoque automatiquement les instructions SIMD appropriées sur n'importe quel processeur CPU ? Faiss ne prend pas en charge la sélection automatique des instructions SIMD et les utilisateurs doivent spécifier manuellement l'indicateur SIMD (par exemple, "-msse4") pendant la compilation. Cependant, Knowhere est construit en remaniant la base de code de Faiss. Les fonctions communes (par exemple, le calcul de similarité) qui dépendent des accélérations SIMD sont supprimées. Ensuite, pour chaque fonction, quatre versions (SSE, AVX, AVX2, AVX512) sont implémentées et chacune est placée dans un fichier source séparé. Les fichiers sources sont ensuite compilés individuellement avec le drapeau SIMD correspondant. Ainsi, au moment de l'exécution, Knowhere peut automatiquement choisir les instructions SIMD les mieux adaptées en fonction des drapeaux actuels de l'unité centrale et lier les bons pointeurs de fonction à l'aide de crochets.

5. Autres optimisations des performances

Lire Milvus : A Purpose-Built Vector Data Management System pour en savoir plus sur l'optimisation des performances de Knowhere.

Comprendre le code de Knowhere

Comme mentionné dans la première section, Knowhere ne gère que les opérations de recherche vectorielle. Par conséquent, Knowhere ne traite que le champ vectoriel d'une entité (actuellement, un seul champ vectoriel est supporté pour les entités d'une collection). La construction d'index et la recherche de similarité vectorielle sont également ciblées sur le champ vectoriel d'un segment. Pour mieux comprendre le modèle de données, lisez le blog ici.

entity fields champs d'entité

Index

L'index est un type de structure de données indépendante des données vectorielles originales. L'indexation nécessite quatre étapes : créer un index, entraîner les données, insérer les données et construire un index.

Pour certaines applications d'intelligence artificielle, l'entraînement des ensembles de données est un processus distinct de la recherche vectorielle. Dans ce type d'application, les données des ensembles de données sont d'abord formées, puis insérées dans une base de données vectorielles telle que Milvus pour la recherche de similarités. Les ensembles de données ouverts tels que sift1M et sift1B fournissent des données pour l'entraînement et le test. Cependant, dans Knowhere, les données pour l'entraînement et la recherche sont mélangées. En d'autres termes, Knowhere entraîne toutes les données d'un segment, puis insère toutes les données entraînées et construit un index pour elles.

Structure du code de Knowhere

DataObj est la classe de base de toutes les structures de données dans Knowhere. Size() est la seule méthode virtuelle de DataObj. La classe Index hérite de DataObj avec un champ nommé "size_". La classe Index possède également deux méthodes virtuelles - Serialize() et Load(). La classe VecIndex, dérivée de la classe Index, est la classe de base virtuelle pour tous les index vectoriels. VecIndex fournit les méthodes suivantes : Train(), Query(), GetStatistics(), et ClearStatistics().

base clase classe de base

Les autres types d'index sont énumérés à droite dans la figure ci-dessus.

  • L'index Faiss a deux sous-classes : FaissBaseIndex pour tous les index sur les vecteurs à virgule flottante et FaissBaseBinaryIndex pour tous les index sur les vecteurs binaires.
  • GPUIndex est la classe de base pour tous les index GPU Faiss.
  • OffsetBaseIndex est la classe de base pour tous les index auto-développés. Seul l'identifiant du vecteur est stocké dans le fichier d'index. Par conséquent, la taille d'un fichier d'index pour des vecteurs à 128 dimensions peut être réduite de deux ordres de grandeur. Nous recommandons de prendre également en considération les vecteurs originaux lorsque ce type d'index est utilisé pour la recherche de similarités vectorielles.

IDMAP IDMAP

Techniquement parlant, IDMAP n'est pas un index, mais est plutôt utilisé pour la recherche par force brute. Lorsque des vecteurs sont insérés dans la base de données vectorielles, aucune formation de données ni construction d'index n'est nécessaire. Les recherches sont effectuées directement sur les données vectorielles insérées.

Toutefois, pour des raisons de cohérence du code, IDMAP hérite également de la classe VecIndex et de toutes ses interfaces virtuelles. L'utilisation d'IDMAP est la même que celle des autres index.

IVF IVF

Les index IVF (fichier inversé) sont les plus fréquemment utilisés. La classe IVF est dérivée des classes VecIndex et FaissBaseIndex, et s'étend aux classes IVFSQ et IVFPQ. GPUIVF est dérivé de GPUIndex et IVF. GPUIVF s'étend ensuite à GPUIVFSQ et GPUIVFPQ.

IVFSQHybrid est une classe d'index hybride auto-développée qui est exécutée par quantification grossière sur le GPU. La recherche dans le seau est exécutée par l'unité centrale. Ce type d'index permet de réduire les copies de mémoire entre le CPU et le GPU en exploitant la puissance de calcul du GPU. IVFSQHybrid a le même taux de rappel que GPUIVFSQ mais offre de meilleures performances.

La structure des classes de base pour les index binaires est relativement plus simple. BinaryIDMAP et BinaryIVF sont dérivés de FaissBaseBinaryIndex et VecIndex.

third-party index index de tiers

Actuellement, seuls deux types d'index tiers sont pris en charge en dehors de Faiss : l'index basé sur les arbres Annoy et l'index basé sur les graphes HNSW. Ces deux index tiers courants et fréquemment utilisés sont tous deux dérivés de VecIndex.

Ajouter des index à Knowhere

Si vous souhaitez ajouter de nouveaux index à Knowhere, vous pouvez d'abord vous référer aux index existants :

  • Pour ajouter un index basé sur la quantification, reportez-vous à IVF_FLAT.
  • Pour ajouter un index basé sur les graphes, reportez-vous à HNSW.
  • Pour ajouter un index basé sur les arbres, reportez-vous à Annoy.

Après avoir consulté les index existants, vous pouvez suivre les étapes ci-dessous pour ajouter un nouvel index à Knowhere.

  1. Ajoutez le nom du nouvel index dans IndexEnum. Le type de données est une chaîne.
  2. Ajoutez un contrôle de validation des données sur le nouvel index dans le fichier ConfAdapter.cpp. Le contrôle de validation sert principalement à valider les paramètres de formation des données et de requête.
  3. Créez un nouveau fichier pour le nouvel index. La classe de base du nouvel index doit inclure VecIndex et l'interface virtuelle nécessaire de VecIndex.
  4. Ajoutez la logique de construction de l'index pour le nouvel index dans VecIndexFactory::CreateVecIndex().
  5. Ajoutez un test unitaire dans le répertoire unittest.

À propos de la série Deep Dive

Avec l'annonce officielle de la disponibilité générale de Milvus 2.0, nous avons orchestré cette série de blogs Milvus Deep Dive afin de fournir une interprétation approfondie de l'architecture et du code source de Milvus. Les sujets abordés dans cette série de blogs sont les suivants

Like the article? Spread the word

Continuer à Lire