🚀 Zilliz Cloudを無料で試す、完全管理型のMilvus—10倍の高速パフォーマンスを体験しよう!今すぐ試す>>

milvus-logo
LFAI
  • Home
  • Blog
  • ベクターデータベースを最適化し、RAG駆動型生成AIを強化する

ベクターデータベースを最適化し、RAG駆動型生成AIを強化する

  • Engineering
May 13, 2024
Cathy Zhang, Dr. Malini Bhandaru

この投稿はIntelのMedium Channelに掲載されたもので、許可を得てここに再掲載しています。


RAG使用時にベクターデータベースを最適化する2つの方法

写真:Ilya PavlovonUnsplash

Cathy ZhangとDr. Malini Bhandaruによる寄稿:Lin Yang、Changyan Liu

生成AI(GenAI)モデルは、私たちの日常生活で急激に採用されつつあり、外部ソースから事実をフェッチすることによって応答精度と信頼性を高めるために使用される技術である検索拡張生成(RAG)によって改善されつつある。RAGは、通常の大規模言語モデル(LLM)がコンテキストを理解し、ベクトルとして保存された非構造化データの巨大なデータベースを活用することで幻覚を減らすのを助ける。

RAGは、より多くの文脈情報を取得し、より良い応答を生成するのに役立つが、依拠するベクトル・データベースは、豊富なコンテンツを提供するためにますます大きくなっている。兆パラメータのLLMが目前に迫っているように、数十億のベクトル・データベースもそう遠くはない。最適化エンジニアとして、私たちはベクターデータベースのパフォーマンスを向上させ、データのロードを高速化し、インデックスの作成を高速化することで、新しいデータが追加されても検索速度を確保できないかと考えました。そうすることで、ユーザーの待ち時間を短縮できるだけでなく、RAGベースのAIソリューションをもう少し持続可能なものにすることができます。

この記事では、ベクターデータベースとそのベンチマークフレームワーク、さまざまな側面に取り組むためのデータセット、パフォーマンス分析に使用するツールについて詳しく説明します。また、パフォーマンスと持続可能性に影響を与える最適化の旅でインスピレーションを得るために、人気のある2つのベクトルデータベースソリューションにおける最適化の成果を紹介します。

ベクトルデータベースを理解する

データが構造化された方法で保存される従来のリレーショナルデータベースや非リレーショナルデータベースとは異なり、ベクトルデータベースには、埋め込み関数または変換関数を使用して構築されたベクトルと呼ばれる個々のデータ項目の数学的表現が含まれます。ベクトルは一般的に特徴や意味的な意味を表し、短くても長くてもよい。ベクトルデータベースは、ユークリッド類似度、ドット積類似度、余弦類似度などの距離メトリック(距離が近いほど類似度が高いことを意味する)を用いた類似度検索によってベクトル検索を行う。

検索プロセスを高速化するために、ベクトルデータはインデックス作成メカニズムを使って整理される。これらの構成方法の例としては、フラット構造、インバーテッド・ファイル(IVF)、 階層的ナビゲーシブル・スモール・ワールド(HNSW)ローカリティ・センシティブ・ハッシング(LSH)などがある。これらの方法はそれぞれ、必要なときに類似したベクトルを取り出す効率性と有効性に貢献している。

GenAIシステムでベクターデータベースをどのように使うかを検証してみよう。図1は、ベクターデータベースへのデータのロードと、GenAIアプリケーションのコンテキストでの使用の両方を示しています。プロンプトを入力すると、データベースでベクトルを生成するのと同じ変換処理が行われます。この変換されたベクトルプロンプトは、ベクトルデータベースから類似のベクトルを検索するために使用されます。これらの検索された項目は、基本的に会話の記憶として機能し、LLMの動作と同様に、プロンプトのコンテキスト履歴を提供する。この機能は、自然言語処理、コンピュータビジョン、レコメンデーションシステムなど、意味理解やデータマッチングを必要とする領域で特に有利である。最初のプロンプトは、その後、検索された要素と「マージ」され、コンテキストが提供され、LLMが元の学習データだけに頼るのではなく、提供されたコンテキストに基づいて応答を策定するのを支援する。

図1.RAGアプリケーションのアーキテクチャ。

ベクトルは高速検索のために保存され、インデックスが付けられる。ベクトルデータベースには、ベクトルを格納するために拡張された従来のデータベースと、専用に構築されたベクトルデータベースの2種類がある。ベクトルをサポートする従来のデータベースの例としては、RedispgvectorElasticsearchOpenSearchなどがあります。専用のベクターデータベースの例としては、プロプライエタリなソリューションであるZillizや Pinecone、オープンソースプロジェクトであるMilvusWeaviateQdrantFaissChromaなどがあります。ベクターデータベースについては、GitHubのLangChainと OpenAI Cookbookで学ぶことができる。

ここでは、MilvusとRedisというそれぞれのカテゴリーから1つずつ詳しく見ていこう。

パフォーマンスの改善

最適化に入る前に、ベクターデータベースがどのように評価されるのか、いくつかの評価フレームワーク、利用可能なパフォーマンス分析ツールについておさらいしましょう。

パフォーマンス指標

ベクターデータベースのパフォーマンス測定に役立つ主なメトリクスを見てみましょう。

  • ロードレイテンシは、ベクトルデータベースのメモリにデータをロードし、インデックスを構築するのに必要な時間を測定します。インデックスとは、類似性や距離に基づいてベクトルデータを効率的に整理し、検索するために使用されるデータ構造です。インメモリインデックスの種類には、フラットインデックスIVF_FLATIVF_PQ、HNSWスケーラブル最近傍(ScaNN)、 DiskANNなどがあります。
  • Recallとは、検索アルゴリズムによって検索された上位K個の結果の中で、真の一致、つまり関連する項目が見つかった割合のことである。Recall 値が高いほど、関連アイテムの検索が優れていることを示す。
  • Queries per second (QPS)は、ベクトルデータベースが入力されたクエリを処理できる速度である。QPS値が高いほど、クエリ処理能力とシステムスループットが優れていることを意味する。

ベンチマークフレームワーク

図2.ベクトルデータベースベンチマーキングのフレームワーク

ベクトルデータベースのベンチマークには、ベクトルデータベースサーバーとクライアントが必要です。性能テストでは、2つの有名なオープンソースツールを使用した。

  • VectorDBBenchZillizによって開発され、オープンソース化されたVectorDBBenchは、様々なインデックスタイプを持つ様々なベクトルデータベースのテストを支援し、便利なウェブインターフェースを提供する。
  • vector-db-benchmarkQdrantによって開発されオープンソース化されたvector-db-benchmarkは、HNSWインデックスタイプの典型的なベクトルデータベースのテストを支援する。コマンドラインでテストを実行し、Docker Compose__fileを提供してサーバコンポーネントの起動を簡素化します。

図3.ベンチマークテストの実行に使用されるvector-db-benchmarkコマンドの例。

しかし、ベンチマークフレームワークは方程式の一部に過ぎません。大量のデータを扱う能力、さまざまなベクトルサイズ、検索速度など、ベクトル・データベース・ソリューション自体のさまざまな側面を検証するデータが必要です。そこで、利用可能な公開データセットをいくつか見てみましょう。

ベクターデータベースを試すための公開データセット

大規模なデータセットは、負荷の待ち時間やリソースの割り当てをテストするのに適しています。データセットの中には高次元のデータもあり、類似性の計算速度をテストするのに適しています。

25次元から2048次元までのデータセットがある。オープンな画像コレクションであるLAIONデータセットは、安定拡散生成モデルのような非常に大規模な視覚・言語ディープニューラルモデルの学習に使用されている。OpenAIのデータセットである5Mベクトル(それぞれ1536次元)は、VectorDBBenchが生データに対してOpenAIを実行することで作成された。各ベクトルの要素がFLOAT型であることを考えると、ベクトルだけを保存するために約29GB(5M * 1536 * 4)のメモリが必要で、さらにインデックスやその他のメタデータを保持するために同程度のメモリが追加され、合計58GBのメモリがテスト用に必要です。vector-db-benchmarkツールを使う場合は、結果を保存するのに十分なディスクストレージを確保する。

ロード・レイテンシーをテストするには、deep-image-96-angularが提供する大規模なベクター・コレクションが必要である。インデックス生成と類似度計算のパフォーマンスをテストするためには、高次元のベクトルがより大きなストレスとなる。このため、我々は1536次元ベクトルからなる500Kデータセットを選択した。

パフォーマンス・ツール

注目すべきメトリクスを特定するためにシステムにストレスを与える方法について説明したが、より低いレベルで何が起きているかを検証してみよう。これらはデータベースの挙動を知る手がかりとなり、特に問題箇所を特定するのに役立ちます。

Linux のtopユーティリティはシステム性能情報を提供します。しかし、Linuxのperfツールはより深い洞察を提供します。詳細については、Linux perf の例Intel トップダウン・マイクロアーキテクチャー解析法を読むことをお勧めします。さらにもう1つのツールはIntel® vTune™ Profilerで、アプリケーションだけでなく、HPC、クラウド、IoT、メディア、ストレージなど様々なワークロードのシステム性能と構成を最適化する際に役立ちます。

Milvusベクター・データベースの最適化

Milvusベクトルデータベースの性能向上を試みたいくつかの例を見ていきましょう。

データノード・バッファ書き込みにおけるメモリ移動オーバーヘッドの削減

Milvusの書き込みパスのプロキシはMsgStreamを介してログブローカにデータを書き込みます。その後、データノードがデータを消費し、セグメントに変換して保存します。セグメントは新しく挿入されたデータをマージします。マージロジックは、古いデータと挿入される新しいデータの両方を保持/移動するために新しいバッファを割り当て、次のデータマージのために新しいバッファを古いデータとして返します。この結果、古いデータは徐々に大きくなり、データ移動が遅くなる。Perf プロファイルでは、このロジックのオーバーヘッドが高いことが示された。

図4.ベクター・データベースにおけるデータのマージと移動は、高いパフォーマンス・オーバーヘッドを発生させる。

私たちはマージ・バッファのロジックを変更し、挿入する新しいデータを古いデータに直接追加することで、新しいバッファの確保と大きな古いデータの移動を回避しました。Perf プロファイルは、このロジックにオーバーヘッドがないことを確認しています。マイクロコードメトリクスのmetric_CPU operating frequencymetric_CPU utilizationは、システムが長いメモリ移動を待つ必要がなくなったことと一致する改善を示しています。ロードレイテンシは60%以上改善した。この改善はGitHubに掲載されている。

図5.コピーを減らすことで、ロード・レイテンシが50パーセント以上改善された。

メモリ割り当てのオーバーヘッドを削減した反転インデックス構築

Milvusの検索エンジンであるKnowhereは転置ファイル(IVF)インデックスを作成するためのクラスタデータのトレーニングにElkan k-meansアルゴリズムを採用しています。データトレーニングの各ラウンドは反復回数を定義します。このカウントが大きいほど、学習結果が良くなります。しかし、これはElkanアルゴリズムがより頻繁に呼び出されることを意味します。

Elkanアルゴリズムは、実行のたびにメモリの確保と解放を行う。具体的には、対角要素を除いた対称行列データの半分のサイズのメモリを確保します。Knowhereでは、Elkanアルゴリズムが使用する対称行列の次元は1024に設定されており、その結果、メモリサイズは約2MBになります。これは、各トレーニングラウンドでElkanが2MBのメモリの確保と解放を繰り返すことを意味します。

Perf プロファイリングデータは、頻繁に大きなメモリ割り当てアクティビティを示していた。実際、仮想メモリ領域(VMA)の割り当て、物理ページの割り当て、ページマップのセットアップ、カーネル内のメモリcgroup統計の更新がトリガーされました。このような大規模なメモリアロケーション/デアロケーション活動のパターンは、状況によっては、メモリの断片化を悪化させる可能性もある。これは重大な税金である。

IndexFlatElkan構造体は、Elkanアルゴリズムをサポートするために特別に設計・構築されています。各データトレーニング処理では、IndexFlatElkanインスタンスが初期化されます。Elkanアルゴリズムにおける頻繁なメモリ割り当てと割り当て解除によるパフォーマンスへの影響を軽減するため、コードロジックをリファクタリングし、Elkanアルゴリズム関数の外側にあるメモリ管理をIndexFlatElkanの構築プロセスに移しました。これにより、メモリ割り当てが初期化フェーズで一度だけ行われ、その後のElkanアルゴリズム関数の呼び出しはすべて現在のデータトレーニングプロセスから行われるようになり、ロードレイテンシが約3%改善されました。Knowhereパッチはこちら

ソフトウェア・プリフェッチによるRedisベクトル検索の高速化

従来のインメモリ・キーバリュー・データストアとして人気の高いRedisは、最近ベクトル検索のサポートを開始しました。典型的なキー・バリュー・ストアを超えるために、Redisは拡張モジュールを提供しており、RediSearchモジュールはRedis内で直接ベクトルの保存と検索を容易にします。

Redisは、ベクトル類似検索のために、ブルートフォースとHNSWという2つのアルゴリズムをサポートしています。HNSWアルゴリズムは、高次元空間の近似最近傍を効率的に見つけるために特別に作られています。candidate_setという優先キューを使って、距離計算のためのすべてのベクトル候補を管理します。

各ベクトル候補は、ベクトルデータに加えて実質的なメタデータを含む。その結果、候補をメモリからロードする際にデータキャッシュのミスが発生し、処理遅延が発生することがある。我々の最適化では、ソフトウェアプリフェッチを導入し、現在の候補を処理中に次の候補をプロアクティブにロードします。この改良により、シングルインスタンスのRedisセットアップにおけるベクトル類似検索のスループットが2~3パーセント向上しました。このパッチは現在アップストリーム化中である。

混合アセンブリ・コードのペナルティを防ぐためのGCCデフォルト動作の変更

パフォーマンスを最大化するために、頻繁に使用されるコード・セクションはアセンブリで手書きされることが多い。しかし、コードの異なるセグメントが異なる人または異なる時点で書かれた場合、インテル® Advanced Vector Extensions 512 (インテル® AVX-512)ストリーミング SIMD 拡張命令 (SSE) などの互換性のないアセンブリー命令セットが使用されることがあります。適切にコンパイルされないと、混合コードはパフォーマンス・ペナルティになります。インテル® AVX 命令と SSE 命令の混在については、こちらを参照してください。

混合モードのアセンブリー・コードを使用していて、VZEROUPPER でコンパイルされておらず、パフォーマンス・ペナルティが発生しているかどうかは簡単に判断できます。これは、sudo perf stat -e 'assists.sse_avx_mix/event/event=0xc1,umask=0x10/' <workload>のようなperfコマンドで確認できます。OSがイベントをサポートしていない場合は、cpu/event=0xc1,umask=0x10,name=assists_sse_avx_mix/を使用してください。

ClangコンパイラーはデフォルトでVZEROUPPERを挿入し、混合モードのペナルティーを回避します。しかし、GCCコンパイラは-O2または-O3コンパイラ・フラグが指定されたときだけVZEROUPPERを挿入します。我々はGCCチームに連絡し、この問題を説明したところ、現在ではデフォルトで混合モードのアセンブリ・コードを正しく処理するようになった。

ベクター・データベースの最適化開始

ベクターデータベースはGenAIにおいて不可欠な役割を果たしており、より高品質な応答を生成するためにますます大きくなっている。最適化に関して、AIアプリケーションは、ベンチマークフレームワークやストレス入力とともに標準的なパフォーマンス分析ツールを使用したときにその秘密が明らかになるという点で、他のソフトウェアアプリケーションと変わりません。

これらのツールを使用して、不要なメモリ割り当て、命令のプリフェッチの失敗、および不正なコンパイラオプションの使用に関連するパフォーマンスの罠を発見しました。この発見に基づいて、Milvus、Knowhere、Redis、およびGCCコンパイラのアップストリーム機能強化を行い、AIのパフォーマンスと持続可能性を少しでも向上させることに貢献した。ベクトル・データベースは、最適化に取り組む価値のある重要なアプリケーション・クラスです。本記事がその一助となれば幸いである。

Like the article? Spread the word

続けて読む