大規模モデルの突破 | Alluxio による AI 大規模モデルのトレーニング - 成功事例 (1)

詳細については、「Alluxio Helps AI Large Model Training Winning Guide」を参照してください。

[ケース 1: Zhihu] Zhihu でのマルチクラウド キャッシュの探索: UnionStore から Alluxio まで

著者: Hu Mengyu - Zhihu ビッグデータ インフラストラクチャ開発エンジニア (内容は InfoQ から転載)

1. 背景

クラウド ネイティブ テクノロジの急速な発展に伴い、主要なパブリック クラウド ベンダーが提供するクラウド サービスはますます標準化し、信頼性が高く、使いやすくなりました。クラウド ネイティブ テクノロジを使用すると、ユーザーは低コストでさまざまなクラウドにビジネスを展開できるだけでなく、特定の技術分野で各クラウド ベンダーの利点やサービスを享受できるため、マルチクラウド アーキテクチャは非常に人気があります。
Zhihu は現在、主に次の考慮事項に基づいてマルチクラウド アーキテクチャを採用しています。


  • マルチアクティブ サービス: 不可抗力により 1 つのデータ センターが通常のサービスを提供できなくなり、ビジネスが「ワン ポット エンド」になることを防ぐために、同じサービスを異なるデータ センターに展開します。
  • 容量の拡張: 一般に、企業のサーバー規模が 10,000 ユニットに達すると、単一のデータセンターでその後のビジネスの拡張ニーズをサポートするのは困難になります。
  • コスト削減と効率化: 同じサービスでもクラウドベンダーによって価格や運用保守能力が異なるため、クラウドサービスがニーズを満たすことを前提に、できるだけ安く享受できる理想の状態を実現したいと考えています。の価格。
    Zhihu には現在複数のデータセンターがあり、主なコンピューター室は次のとおりです。
  • オンライン コンピューター ルーム: 主に遅延に敏感な Zhihu メイン サイトでユーザーへの直接サービス (コメント、回答など) を展開します。
  • オフライン コンピューター ルーム:主にオフライン ストレージとコンピューティング関連のサービスを展開します。これらのサービスは遅延には敏感ではありませんが、スループットには高い要件があります。


2 つのデータ センターは専用線で接続されており、多くの重要なサービスはコンピューター室間の通話に専用線に依存しているため、専用線の安定性を維持することが非常に重要です。専用線トラフィックは、専用線の安定性を測る重要な指標の一つであり、専用線トラフィックが専用線の定格帯域に達すると、専用線をまたいだサービス間の通話でタイムアウトや障害が大量に発生する原因となります。 。
一般的に、サービスのスループットはそれほど高くはなく、専用線の帯域幅の上限には遠く及ばず、専用線の帯域幅の半分にも満たないのですが、弊社ではいくつかの特殊な状況があります。アルゴリズム シナリオ: アルゴリズム モデルのトレーニングはオフラインのコンピューター ルームで行われ、HDFS 上の大規模なデータセットと、大規模な分散トレーニング用の Spark クラスターおよび機械学習プラットフォームに依存します。トレーニングされたモデルの結果は HDFS に保存され、モデルモデルがオンラインになると、アルゴリズム サービスはオンライン コンピューター ルームから専用回線を介してオフライン HDFS 上のモデル ファイルを読み取り、アルゴリズム サービスには通常、数十、場合によっては数百のコンテナーがあります。これらのコンテナは HDFS 上のファイルを同時に読み取るため、専用線の帯域幅がフルに活用され、他の専用線間サービスに影響を及ぼします。

2. 複数の HDFS クラスター

初期の頃、私たちはアルゴリズム モデルをコンピューター ルーム間で読み取るという問題を非常に単純かつ粗雑な方法で解決しましたが、アルゴリズム ビジネスで使用するために新しい HDFS クラスターのセットをオンライン コンピューター ルームに展開しました。 1) 出力モデル: モデルは Spark クラスターによって生成される
、または機械学習プラットフォームのトレーニング出力はオフライン HDFS クラスターに保存されます;
2) モデルのコピー: モデルが生成された後、オフライン スケジューリング タスクオンラインにする必要があるモデルをオンライン HDFS クラスターに定期的にコピーします;
3) モデルの読み取り: アルゴリズム コンテナーがオンライン HDFS クラスターからロードされます モデルをオンラインで読み取ります。

マルチ HDFS クラスター アーキテクチャは専用線トラフィックの問題を解決しますが、まだいくつかの問題があります。

  1. 複数の HDFS クラスターは保守が容易ではなく、運用および保守担当者の負担が増大します。
  2. コピー スクリプトは企業自身が実装する必要があり、新しいモデルがリリースされるたびにコピー スクリプトを同期的に変更する必要があるため、保守が不便です。
  3. オンライン HDFS クラスターのファイルは、コストを削減するために企業によって定期的に手動で削除される必要があり、運用リスクが高くなります。
  4. オンライン HDFS とオフライン HDFS ではファイルビューが一致しないため、ユーザーが HDFS を使用する場合、どの HDFS を使用しているのかを把握する必要があり、複数のアドレスを保存する必要があり、精神的な負担が大きくなります。
  5. たとえば、超高同時読み取りの場合、特定のモデル ファイルを読み取るためにアルゴリズムが一度に数百のコンテナを起動すると、DataNode の負荷が高くなりすぎます。コピーを追加することで解決できますが、また、保管コストも高くなります。

上記の問題点に基づいて、私たちはマルチクラウド キャッシュ サービスである UnionStore を自社開発しました。

3. 自社開発コンポーネント UnionStore

3.1 はじめに
UnionStore は、その名前が示すように、共同ストレージを意味し、HDFS 上のデータにアクセスするための標準 S3 プロトコルを提供し、オブジェクト ストレージをコンピュータ ルーム間のキャッシュとして使用します。現在、Zhihu には UnionStore の 2 つの使用シナリオがあります。
モデル オンライン シナリオ: オンライン コンピューター ルームに展開され、コンピューター ルーム間のキャッシュとして使用されます。
ユーザーが UnionStore からファイルの読み取りを要求すると、最初にファイルがアップロードされているかどうかが確認されます。オブジェクトストレージへ:

  • ファイルがオブジェクト ストレージにすでに存在する場合は、ファイルをオブジェクト ストレージから直接読み取り、ユーザーに返します。
  • ファイルがオブジェクト ストレージに存在しない場合、UnionStore はまずオフライン HDFS 上のファイルをオンライン コンピュータ ルームのオブジェクト ストレージにアップロードし、次にオブジェクト ストレージからファイルを読み取ってユーザーに返します。期間が経過すると、ユーザーのリクエストはブロックされます。これは、オブジェクト ストレージを使用してコンピューター ルーム間キャッシュのレイヤーを作成するのと同じです。


モデル トレーニング シナリオ: オフラインのコンピューター ルームにデプロイされ、HDFS プロキシとして使用されます。目的は、ビジネスに S3 プロトコルの HDFS アクセス方法を提供することです。s3fs-fuse を通じて、ビジネスは HDFS をローカル ディレクトリにマウントし、トレーニングを読み取ることができますモデルトレーニング用のデータ。
モデル トレーニング シナリオは、UnionStore がオンラインになった後の拡張シナリオです。これまで HDFS に POSIX をマウントするために多くの方法を試してきましたが、結果は理想的ではなく、主に再試行の面に反映されました。UnionStore は S3 プロトコルと s3fs を提供するだけです-fuse Heavy トライアルは良好だったので、最終的に UnionStore + s3fs-fuse を選択して HDFS にローカル ディレクトリをマウントしました。
そのワークフローは次のとおりです。

以前のマルチ HDFS クラスター ソリューションと比較した場合、UnionStore の利点は次のとおりです:
1) UnionStore は S3 プロトコルを提供し、各プログラミング言語は HDFS プロトコルよりも S3 プロトコルをサポートし、ツールが比較的豊富です。2)
UnionStoreファイルが自動的にキャッシュされるため、ユーザーがモデルを手動でコピーする必要がなく、コピー スクリプトの開発とメンテナンスが不要になります;
3) 統合されたファイル ビューを提供します。メタデータはリアルタイムで HDFS を要求するため、ファイル ビューは HDFS と強力に一致します。 ;
4) オフライン HDFS クラスターでは、ファイル ストレージ機能がオブジェクト ストレージによって提供されるため、サーバー コストが大幅に節約されます; 5
) ファイルの有効期限はオブジェクト ストレージ自体によって提供される機能に依存するため、それを実装する必要はありません6
) UnionStore はクラウドネイティブな方法でサービスを提供し、 k8s にデプロイされ、各コンテナーはステートレス ノードであり、簡単にスケールアップおよびスケールダウンできます。オブジェクト ストレージのパフォーマンスが十分であれば、同様の DataNode 負荷過負荷は発生しません。
3.2 実装の詳細
UnionStore の完全なアーキテクチャ図は次のとおりです。


オブジェクト ストレージをキャッシュとして使用する場合、UnionStore には 3 つのコア コンポーネントがあります。
UnionStore サーバー: ステートレス ノード。各ノードは独立してサービスを提供でき、一般にトラフィックを共有するために複数のデプロイメントが使用されます。
オブジェクト ストレージ: オブジェクト ストレージ 。HDFS のキャッシュに使用されます。クラウド プロバイダー上のデータは、対応するクラウド プロバイダーが提供するオブジェクト ストレージを使用し、トラフィック コストはほとんど無視できます。
タスク マネージャー: タスクの保存とキャッシュに使用されるタスク マネージャーは、MySQL と Redis で実装できます。
これら 3 つのコンポーネントに基づいて、UnionStore に一連の便利な機能を実装しました。
ファイル検証: ファイルがオブジェクト ストレージにキャッシュされた後、HDFS 上のファイルが変更された場合、UnionStore はファイルの変更をチェックして、ユーザーが間違ったファイルを読み取らないようにする必要があります。ここでは、HDFS ファイルをオブジェクト ストレージにアップロードするときに、HDFS ファイルのサイズ、最終変更時刻、チェックサム、その他のメタ情報をオブジェクト ストレージ ファイルの UserMetadata に保存します。ユーザーがファイルを読み取るときに、これを確認します。情報の一部であり、情報の検証に合格した場合のみオブジェクトストレージ上のファイルが返却され、検証に失敗した場合はファイルが再キャッシュされ、オブジェクトストレージ上のキャッシュが更新されます。
読み取りおよび書き込みの高速化: オブジェクト ストレージのシングル スレッドの読み取りおよび書き込み速度は約 30 ~ 60 MB/秒であり、HDFS のスループットよりもはるかに低く、特別な処理がなければ、ストレージの読み取りおよび書き込みのニーズを満たすことは困難です。仕事。読み取りに関しては、オブジェクトストレージのRangeReadインターフェースを使用して、オブジェクトストレージ上のデータをマルチスレッドで読み取り、ユーザーに返すことで、HDFSと同等の読み取り速度を実現しています。書き込みに関しては、オブジェクト ストレージの MultiPartUpload インターフェイスを使用して、マルチスレッドで HDFS 上にファイルをアップロードします。これにより、HDFS と同等の書き込み速度も実現できます。
ファイルは 1 回だけキャッシュされます。 UnionStore Server はステートレス ノードとして設計されているため、相互に認識できません。異なるサーバー ノードに対して、キャッシュされていないファイルを要求する複数の要求が同時に存在する場合、ファイルは異なるサーバーによって複数回キャッシュされる可能性があり、専用回線への負荷が増大する可能性があります。この問題を解決するために、タスク マネージャー コンポーネントを導入しました。


  1. サーバー ノードは、キャッシュされていないファイルを読み取るリクエストを受信すると、まずユーザーのリクエストを非同期にブロックし、キャッシュ タスクを生成して、それをタスク マネージャーの待機キューに送信します。
  2. すべてのサーバー ノードは待機キュー内のタスクを巡って競合し続けますが、競合に成功するのは 1 つのノードだけです。このとき、ノードはキャッシュされたタスクを実行キューに入れて実行を開始します。実行中に、次のレポートが表示されます。タスクキューへのハートビート。
  3. 各サーバー ノードは、スタックしたユーザー リクエストを定期的にチェックし、タスク マネージャーで対応するタスクを確認します。タスクが正常に実行されると、ユーザー リクエストをウェイクアップし、キャッシュされたファイルをユーザーに返します。同時に各サーバーは、タスク マネージャーで実行中のタスクを定期的にチェックします。タスクが長期間ハートビートを更新しなかった場合、タスクは実行キューから削除され、待機キューに戻され、再度実行されます。


ここでのすべての状態変更操作はサーバー ノードで発生し、タスク マネージャーはタスク情報を保存し、キュー上でアトミックな操作を提供することのみを担当します。


3.3 制限事項
UnionStore プロジェクトは Zhihu で 2 年間実行されており、初期段階では問題はありませんでしたが、アルゴリズムのビジネス規模が継続的に拡大するにつれて、次のような問題が発生しました: 1) メタデータ キャッシュがない
。メタデータは HDFS に強く依存している HDFS ジッター 頻繁に更新する必要がある一部のモデル ファイルが影響を受けて更新できない場合があります オンライン サービスはオフライン HDFS に強く依存すべきではありません 2) 読み取りおよび書き込みの高速化にはマルチスレッド テクノロジが使用されてい
ます大量の CPU を消費します。UnionStore が大規模だったときは、会社のアルゴリズム チーム全体がデータを読み取るのに必要なコアは数百コアだけでしたが、ビジネス量が増加し続けるにつれて、必要な CPU の数も数千に増加しました。 3) オブジェクト ストレージ容量には上限があり、単一
ファイルの数千件の同時読み取りもパフォーマンスのボトルネックに直面します;
4) UnionStore はキャッシュのみを実現しますが、高パフォーマンスのキャッシュは実現しません。読み込みに10分以上かかり、モデルの更新速度に大きな影響を与える ビジネス開発の制限;
5) キャッシュ中はファイルを返すことができず、初回のファイル読み込みに時間がかかりすぎる。
さらに、もう 1 つの重要なポイントがあります. より活性化を確保するために、機械学習プラットフォームもマルチクラウド アーキテクチャを採用し、複数のコンピューター ルームの展開をサポートします. トレーニング データを読み取る際には、UnionStore から HDFS への直接プロキシを使用しますほとんどのトレーニング データは小さなファイルであり、その数が膨大であるため、キャッシュ プロセスは使用されません。小さなファイルのキャッシュを通過すると、キャッシュ タスクがタスク キューに長時間キューイングされ、読み取りの適時性を保証することが難しいため、HDFS を直接プロキシします。この利用方法でも、学習データの規模が拡大した場合には、依然として専用線の帯域がボトルネックとなる。

上記の問題点により、私たちは 2 つの選択肢に直面することになります: 1 つは、ローカル SSD やメモリ キャッシュのサポートなど、UnionStore が高性能のキャッシュ機能を備えられるように、UnionStore の反復処理を続けることです。もう 1 つは、完全に置き換える適切なオープンソース ソリューションを見つけることです。 UnionStoreの利用シーンをご紹介します。人材の貴重さを踏まえ、私たちは後者を選択しました。

4. Alluxio を使用して UnionStore を置き換える

1. 調査業界で主流のファイル システムを調査した結果、Alluxio の方が今回のシナリオに適していることが
わかりました。その理由は次のとおりです。
ビジネス側はモデル ファイルを他のファイル システムに書き込む必要はなく、現状を維持して HDFS に書き込むだけで済みます; 2)
メタデータとデータ キャッシュ: Alluxio はカスタム キャッシュ メタデータとデータをサポートしているため、キャッシュされたデータを読み取るときにファイルは HDFS の影響をまったく受けません。現在、UnionStore の QPS は約 20K ~ 30K で、キャッシュ メタデータは NameNode への負荷を大幅に軽減し、オフライン シナリオをフィードバックできます。3) 豊富な UFS サポート: さまざまな UFS をサポートします。
オブジェクト ストレージなどの HDFSに加えて、データ レイク シナリオに対する強力なサポートも提供します
; 4) アドホック クエリの高速化: Zhihu のアドホック エンジンは Spark と Presto を使用し、Alluxio はこれら 2 つのエンジンを適切にサポートします;
5) 豊富なアクセス インターフェイス: Alluxio が提供する S3 プロキシ コンポーネントは、S3 プロトコルと完全に互換性があります。UnionStore から Alluxio にモデルをオンラインで移行するコストはほとんど無視できます。さらに、Alluxio が提供する Alluxio ヒューズにはローカル メタデータ キャッシュとデータ キャッシュがあります。S3ビジネスで以前に使用されていたヒューズのパフォーマンスは優れており、モデルのトレーニング シナリオをちょうど満たしています。
6) 活発なコミュニティ: Alluxio コミュニティは非常に活発で、調査期間中は基本的に熱心なネットユーザーがおり、コミュニケーション グループにはタイムリーに返信し、問題に対して半日以上返信がないことはほとんどありません。
Alluxio に関する調査には、私たちのニーズを満たしただけでなく、多くの追加機能も提供してくれて、とてもうれしい驚きでした。Alluxio を社内でテストしました。100G ファイルを使用してシングルスレッド読み取りテストを実行し、複数のテストの平均値を取りました。結果は次のとおりです。

このうち、HDFS は OS レベルでのキャッシュを伴うため、200MB/秒から 500MB/秒の範囲で変動が最も大きくなりますが、UnionStore と Alluxio はキャッシュにヒットする際の安定性が非常に高いです。
2. クラスター計画
私たちの計画では、各コンピューター室に 1 セットの Alluxio が導入され、高性能 NVME ディスクが HDFS とオブジェクト ストレージ上のデータのキャッシュに使用され、企業に大規模なデータ アクセラレーション サービスを提供します。
ビジネス利用シナリオに応じて、Alluxio クラスターは 2 つのタイプに分類されます。
モデル オンライン アクセラレーション クラスター: Alluxio クラスターはモデル自体をキャッシュし、S3 プロキシを使用して読み取り専用サービスを外部に提供し、モデルのオンライン
モデル トレーニングを高速化します。 アクセラレーション クラスター: Alluxio クラスターはモデル トレーニング データをキャッシュし、Alluxio ヒューズを使用してキャッシュしますHDFS 上のデータとメタデータをローカルで使用し、モデルのトレーニングを高速化します。出力モデルは、永続ストレージ用の Alluxio ヒューズを介して HDFS に直接書き込まれます。

3. モデル オンライン シナリオの適応
3.1 シナリオの特徴
私たちのモデル オンライン シナリオには次の特徴があります:
1) ユーザーは S3 プロトコルを使用してモデル ファイルを読み取ります;
2) ユーザーがモデル データを HDFS に書き込んだ後、すぐに読み取る必要があります。 、生成されたデータ 出力と読み取りの間隔は第 2 レベルであり、事前にウォームアップすることはほとんど不可能であり、キャッシュの侵入の問題があります。 3) モデル ファイルは数百、さらには数千人によって読み取られます
。コンテナーを同時に使用すると、トラフィックの増幅は明らかであり、最大の単一モデル読み取りフェッチ時のピーク トラフィックは 1Tb/秒に達することもあります。4) モデル ファイルは短期間のみ使用され
、高同時読み取りが完了すると期限切れとみなされます;
5) 数万のコンテナが数千の K8 ノードに分散されており、単一のコンテナで使用できるリソースが少なくなります。
モデル起動シナリオでは、ビジネスにキャッシュ サービスを提供するために S3 プロキシを選択しました。Alluxio クライアントと Alluxio ヒューズを使用しない理由は、主に次の考慮事項に基づいています。

  1. ユーザーは当初、ファイルの読み取りに S3 プロトコルを使用していましたが、S3 プロキシへの切り替えにはほとんど費用がかかりませんでした。
  2. ビジネス側で使用する言語にはPython、Golang、Javaなどがありますが、Alluxio ClientはJavaベースで実装されており、他の言語は使用するのが面倒です。
  3. 単一コンテナのリソース制限により、CSI を使用してコンテナ内で Alluxio ヒューズを起動することは適切ではありません。ヒューズのパフォーマンスはディスクとメモリのキャッシュに依存するためです。

3.2 クラスターのデプロイ
1 つ目はクラスターのデプロイ方法です。このシナリオでは、Alluxio クラスターは「大規模クラスター ライト クライアント」方法を採用してデプロイします。つまり、S3 を介したビジネスの開始をサポートするのに十分な数のワーカーと S3 プロキシを提供します。プロトコルの同時リクエストが多い場合のアーキテクチャ図は次のとおりです。

クラスターのバージョンは 2.9.2 です。このバージョンでは、S3 プロキシには v1 と v2 の 2 つの実装があり、alluxio.proxy.s3.v2.version.enabled を設定することで切り替えることができます。v2 バージョンには、IO 操作とメタデータ操作を分類し、それらを異なるスレッド プールに渡して処理するという非常に重要な機能があります。この利点は、一般にメタデータ要求の QPS がファイルの読み取りおよび書き込みの QPS よりもはるかに大きいため、IO スレッドによってスタックされることなくメタデータ操作を迅速に実行できることです。この機能は非常に便利で、UnionStore の QPS は約 25K で、操作の 90% はメタデータ アクセスです。
Alluxio クラスター全体にベア メタル マシンのデプロイメントを採用し、Alluxio は k8s デプロイメント方法も提供しますが、バランスを考慮して、次の理由から依然としてベア メタル マシンのデプロイメントを選択しました。

1) 私たちのテスト結果によると、Alluxio Worker は「フルファイアパワー」の条件下でデュアル 10G NIC を簡単に埋めることができます。このとき、NIC がボトルネックになっています。同じ k8s ノードに接続すると、コンテナは脆弱になります。 Alluxio Worker の影響により、十分なネットワーク カード リソースを確保できません。

2) Alluxio Worker はローカル キャッシュとして高性能ディスクに依存しており、他のサービスと混在すると他のプロセスのディスク IO の影響を受けやすいため、最高のパフォーマンスを実現できません。

3) Alluxio Worker はネットワーク カードやディスクなどの物理リソースに大きく依存しているため、これらのリソースは他のサービスとの共有には適していません。強制的に k8s でデプロイすると、k8s ノードが Alluxio Worker の DaemonSet を起動することになる場合がありますが、過去の経験からコンテナ内のストレージにさまざまな奇妙な問題が発生する可能性があるため、実際には k8s でデプロイする必要はありません。これらの問題を解決し、通常のオンラインの進行に影響を与えるのに時間がかかります。

コミュニティのドキュメントで推奨されているように、マスターとジョブ マスター、ワーカーとジョブ ワーカーを同じマシンにデプロイすることに加えて、S3 プロキシとワーカーも混合しました。S3 プロキシはユーザーからはサーバーのように見えますが、Alluxio クラスターにとってはクライアントです。Alluxio にはクライアントに対して非常に重要な最適化機能があります。クライアントとワーカーが同じノード上にある場合、ショートサーキット読み取り機能が使用されます
。を使用できます。ショートサーキット読み取りが有効になっている場合、クライアントはネットワーク リクエストを使用してワーカー上の RPC インターフェイスを呼び出してデータを読み取るのではなく、ローカル ディスク上のデータを直接読み取るため、ネットワーク カードを大幅に節約できます。リソース。S3 Porxy 経由で Alluxio にアクセスする場合、トラフィックは主に次の部分に分割されます。

  1. ファイルは Alluxio にキャッシュされません。ワーカーは UFS からデータを読み取ります。ワーカーが UFS ファイルをキャッシュしている限り、トラフィックのこの部分は存在しません。
  2. ファイルはリモート ワーカーにキャッシュされます: ローカル ワーカーは他のワーカーからデータを読み取ってローカルにキャッシュし、S3 プロキシは一時的にリモート ワーカーからそれを読み取ります。ローカル ワーカーがキャッシュされた後は、トラフィックのこの部分は存在しなくなります。 ;
  3. ファイルはローカル ワーカーにキャッシュされます。トラフィックは S3 プロキシによってローカル ワーカーから読み取られます。トラフィックのこの部分は、ショートサーキット読み取りが有効になった後は存在しません。
  4. ビジネス側が S3 プロキシから読み取るトラフィック。この部分のトラフィックは回避できません。

このうち、1 と 2 の流量は 3 と 4 の流量よりもはるかに小さく、短絡読み取りにより 3 の流量を節約でき、流量の約 30% ~ 50% を節約できます。

2つ目はクラスターの展開規模で、モデル読み込みのシナリオでは、1日あたりの読み込み総量が数ペタバイトに達することもありますが、モデルファイルはすぐに期限切れになるため、ワーカーの容量を大きくする必要はありません。ワーカー ネットワーク カードの総数 読み取りトラフィックをサポートできる帯域幅。ワーカーの数は、ピーク トラフィック/(2/3 * ネットワーク カードの帯域幅) に従って計算できます。ネットワーク カードは、ワーカーが UFS を読み取るため、およびワーカーが相互にデータを同期するためにバッファの 1/3 を予約する必要があります。
最後は Alluxio Master の HA 方式です。Raft を選択しました。テスト中、数億のメタデータと数百 GB のヒープの場合、Master のマスター/スレーブ切り替えは基本的に 10 秒以内に完了し、これは非常に高速です効率的です。ビジネスはほとんど鈍感です。
3.3 稼働開始と
チューニング 稼働開始プロセスは、チューニングのプロセスでもあります。
最初は、小規模モデルの読み取りリクエストを UnionStore から Alluxio S3 プロキシに切り替えるだけでした。その効果は次のとおりです。

その中の各線分はモデルの読み取りリクエストを表し、線分の長さはデータの読み取りにかかる時間を表します。
第 1 段階は内部 UnionStore サービス、第 2 段階は S3 プロキシに直接切り替えたときの状態です。S3 プロキシに切り替えた後、モデル読み取りの平均速度が向上していることがはっきりとわかりますが、つまり、非常にゆっくりと読みたいという要求が時々あります。問題は、モデルが読み取られるとき、常にコールド読み取りである、つまり、モデル データが予熱されていないことです。ファイルが予熱されていない場合、Alluxio からのデータの読み取りは、最大でも HDFS と同じ速度しか達成できません。キャッシュ機能を完全に活用できません。そしてテストを通じて、Alluxio が予熱されていない同じファイルを同時にリクエストすると、パフォーマンスが大幅に低下し、HDFS を直接読み取る速度にさえ到達できないことがわかりました。したがって、ファイルをウォームアップする方法を見つける必要があります。
一般に、ファイルをウォームアップするには次の 2 つの方法があります:
1) ユーザーがファイルの書き込みを終了した後、手動で Alluxio ロード コマンドを呼び出して事前にデータをキャッシュし、読み取り時に必要なファイルがキャッシュされていることを確認します。2) HDFS 監査
に従ってログに記録するか、HDFS の inotify を使用してファイル変更をサブスクライブし、アルゴリズム ディレクトリでファイル変更が見つかるとすぐにキャッシュを Alluxio にロードします。

方法 1 の問題点は、ユーザーの深い参加が必要であり、追加の精神的負担と開発コストがかかること、第 2 に、ユーザーがロード コマンドの呼び出しを制御できないこと、超大規模なディレクトリをロードすると、すべてのキャッシュが無効になることです。 。
方法 2 では、ユーザーが監視パスを指定する必要もあります。パスがファイルの場合、クローズ要求をリッスンする方が便利です。ただし、パスがディレクトリの場合は、一時ファイルや名前の変更などが含まれます。非常に複雑です。ユーザーが新しいモデルを追加するたびに、常に監視への新しいパスを追加する必要があり、追加の通信コストがかかります。また、このシナリオにより、データの出力と読み取りの間隔は 2 秒です。レベルであり、監視ファイル変更リンクが長すぎるため、遅延が発生し、予熱スキームが失敗する可能性があります。

上記の欠点に基づいて、私たちは一連のキャッシュ戦略を設計しました。
遅いコールド リーディング ファイルの本質は、Alluxio を通じてキャッシュされていないファイルを読み取るときに、読み取られたブロックがキャッシュされ、そのブロックが同時にキャッシュされないことです。そこで、S3 プロキシにロジックを追加し、ファイルを読み取るときにファイルをブロックに分割してキャッシュ ブロック タスクを生成し、平均して各ワーカーに送信して非同期キャッシュを実行します。この利点は、クライアントが最初にいくつかのキャッシュされていないブロックを読み取った後、後続のすべてのブロックがキャッシュされており、読み取り速度が非常に速いことです。また、ブロックが事前にキャッシュされるため、キャッシュペネトレーションの問題も軽減され、HDFS トラフィックを 2 倍以上削減できます。

このキャッシュ戦略では、次の点に注意する必要があります。

1) キャッシュ ブロックは非同期である必要があり、すべての例外は通常の読み取り要求に影響を与えることなく処理される必要があります。

2) ブロックをキャッシュするときは、ブロック ID を特定の方法 (ハッシュなど) でワーカー ID にバインドすることをお勧めします。これにより、同じファイルに対して同時リクエストが行われたときに、1 つのファイルに対するキャッシュ リクエストのみがキャッシュされるようになります。同じワーカー上で特定のブロックがヒットした場合、異なるワーカーが UFS から同じブロックを読み取らないようにし、UFS トラフィックを増幅します。

3) S3 プロキシは、ワーカーの通常のキャッシュ ロジックに影響を与えるタスクの送信が多すぎることを避けるために、送信されたキャッシュ ブロック タスクをカウントする必要があります。設定された alluxio.worker.network.async.cache.manager.threads の半分を超えないことが最善です。 max. この構成 ワーカーに代わって非同期キャッシュ要求を処理するスレッドの最大数、デフォルト値は CPU 数の 2 倍です。

4) S3 プロキシは、同じファイルが高い同時実行で読み取られ、ワーカーの非同期キャッシュ キューがいっぱいになるときに、同じブロックに対するキャッシュ リクエストがワーカーに複数回送信されるのを防ぐために、キャッシュに送信されたブロックの重複を排除する必要があります。ワーカーの非同期キャッシュ キューのサイズは、alluxio.worker.network.async.cache.manager.queue.max を構成することで制御され、デフォルトは 512 です。ブロック ID に従って重複排除比較を行うには、ビットマップを使用することをお勧めします。

5) ワーカーの非同期キャッシュ キューがいっぱいでない場合、非同期キャッシュのスレッド数は常に 4 のままです。効率の低下を防ぐために、コードを変更してワーカーの非同期キャッシュの最小スレッド数を増やす必要があります。 #17179を参照してください。

このキャッシュ戦略を開始した後、フェーズ 3 に入りました。フェーズ 3 のスパイクがすべて消え、全体的な速度がわずかに向上していることがわかります。小さなファイル(約 1GB)をキャッシュしているため、改善効果は明ら​​かではありません。テストの結果、このキャッシュ戦略により、大きなファイル (10 GB 以上) の読み取り速度が 3 ~ 5 倍向上する可能性があり、ファイルが大きくなるほど、その効果はより顕著になります。
キャッシュの問題を解決した後、引き続き Read more モデルを S3 プロキシに切り替えます。その効果は次のとおりです。

今回は 3 つのモデルの読み取りリクエストを S3 プロキシに切り替えました。オレンジ色のモデルは以前に S3 プロキシに切り替えたモデルです。今回の新しいモデルは最大 10G、ピーク読み取りトラフィックは 500Gb/秒です。
今回も3つのステージに分かれており、ステージ1はオレンジ色のモデルがS3 Proxyに切り替わり、その他のモデルはUnionStoreを使用しています、オレンジ色のモデルはデータ量が少なくAlluxioにより高速化されているため、読み込み速度が大幅に向上しています。他のモデルと比較すると、数十倍速く読み取ります。
2段階目は他機種をS3 Proxyに切り替えた後の状態で、他機種の読み込み速度は大幅に速くなっているのですが、オレンジ色の機種は他機種の影響を受けて読み込み速度が遅くなっていることが分かります。とても不思議な現象です。最後に、メタデータ キャッシュが有効になっていない理由を突き止めました。メタデータ キャッシュが有効になっていない場合、Alluxio はクライアントからのすべてのリクエストを HDFS に送信し、S3 プロキシも一部のシステム ディレクトリを頻繁にチェックします。メタデータを同期するためにマスターに大きな負担がかかり、パフォーマンスが数千倍も低下する可能性もあります。
このシナリオでは、当初はメタデータ キャッシュを有効にするつもりはありませんでした。主な理由は、キャッシュされた変更ファイルが企業によって変更され、間違ったファイルが読み取られ、モデルの起動に影響が出るのではないかと心配していたからです。ただし、実際の結果から、マスターのパフォーマンスを向上させるにはメタデータ キャッシュを有効にする必要があります。
ビジネス側とのコミュニケーションの後、メタデータの一貫性仕様を策定しました。1
) メタデータ キャッシュは 1 分に設定されます。

2) 新しく追加したファイルはできる限り新しいディレクトリに書き込み、バージョン番号で管理し、古いファイルを変更したり上書きしたりしないでください。

3) 新しいファイルを上書きする必要がある履歴に残されたタスクや、高いメタデータの一貫性が必要なタスクについては、S3 プロキシ上でメタデータを同期するための特別なコマンドを提供し、データが更新された後、ビジネス パーティはメタデータを同期するコマンドを呼び出します。データ。

メタデータ キャッシュを有効にした後、図の 3 番目の段階に来ましたが、S3 プロキシを使用しない初期の読み取り速度と比較して、すべてのモデル データの読み取り速度が大幅に向上していることがわかります。なお、10倍以上というのはAlluxioマシンの台数とネットワークカードが十分な場合に得られる効果であり、実際の使用ではUnionStoreのリソースの半分を使用して同等の効果を実現しました。ユニオンストア。
3.4 S3 プロキシの速度制限
モデルの読み取りシーンで Alluxio を起動する本来の目的は、ビジネス側のモデルの読み取り速度を向上させることですが、Alluxio を介したデータの読み取りが速すぎるため、代わりに速度を制限する必要があります。これは非常に劇的なことです。無制限の速度は非常に深刻な問題に直面します。アルゴリズム コンテナがモデルを読み取るときに、ファイルが大きい場合、S3 プロキシが配置されている物理マシンのネットワーク カードに影響を与えるだけでなく、S3 プロキシのネットワーク カードにも影響を及ぼします。コンテナーが配置されている k8s ホストは時間がかかるため、フル状態になっており、このノード上の他のコンテナーに影響を与えます。

現在、速度制限の実装には主に次のスキームがあります。
ワーカー側の速度制限: 利点はすべてのクライアントに適用されることですが、欠点はクライアントによるショートサーキット読み取りには適用されないことです。このシナリオでは、S3 プロキシは読み取りをショートし、ニーズを満たすことができません。
クライアント速度制限: 利点は、Alluxio ヒューズと S3 プロキシの両方に同時に適用できることです。欠点は、クライアントが設定を変更して制限を回避できることです。同時に、サーバーのバージョンとクライアントのバージョンが異なるため、レート制限に失敗します。
S3 プロキシのレート制限:  S3 プロキシにのみ有効で、他のクライアントおよびワーカーには無効です。
現在の目標はUnionStoreを置き換えることなので、ビジネス側がAlluxioにアクセスする唯一の入り口はS3 Proxyであるため、クライアント速度制限とS3 Proxy速度制限はニーズを満たすことができますが、実装の難易度を考慮して、最終的にSpeedを選択しました。 S3 プロキシ レベルからの制限。
当社は 2 つの速度制限戦略をサポートしています。一方で、S3 プロキシ プロセスのグローバル速度制限はワーカー ネットワーク カードがフルロードから保護するために使用され、他方で、単一接続の速度制限は k8s を保護するために使用されます。ビジネスコンテナが配置されているノード。私たちは速度制限戦略をコミュニティに投稿しました。興味がある場合は、#16866 を参照してください。

4. モデル トレーニング シナリオの適応
4.1 シナリオの特徴
私たちのモデル トレーニング シナリオには次の特徴があります。
1) ほとんどのオープン ソース モデル トレーニング フレームワークはローカル ディレクトリを最もよくサポートしているため、ビジネスには POSIX アクセスを提供する方がよいでしょう。

2) モデルのトレーニング中の主なボトルネックは GPU であり、メモリ、ディスク、ネットワーク カード、CPU などの物理リソースは比較的十分です。

3) GPU マシンはトレーニング タスク以外のタスクを実行せず、サービスの組み合わせはありません。

4) データはスナップショットの形式で管理され、メタデータの一貫性要件はありませんが、HDFS 上で生成された新しいスナップショットを検知する手段が必要です。

モデル トレーニング シナリオでは、キャッシュ サービスを提供するために Alluxio ヒューズを選択する必要があることに疑いの余地はありません。

1. Alluxio ヒューズは POSIX アクセス方式を提供します。

2. Alluxio ヒューズは、メタデータ キャッシュとデータ キャッシュにメモリとディスクを使用でき、GPU マシン上のアイドル状態の物理リソースを最大限に活用できます。

4.2 性能テスト
オンラインにする前に、fio を使用してヒューズの圧力テストを実施しました。
Alluxio ヒューズの構成:


テスト結果は次のとおりです。

上記の結果はすべてヒューズローカルディスクにデータをキャッシュした場合ですが、コンテナのメモリが40Gであるため、1Gファイルと10Gファイルを読み込んだ場合、100Gファイルの2倍の速度になります。 1G および 10G ファイルをキャッシュするには十分なページキャッシュがありますが、100G ファイルには十分なページキャッシュがないため、パフォーマンスは低下しますが、良好な速度も達成でき、全体的な動作は期待どおりです。

4.3 クラスターのデプロイメント
Alluxio ヒューズのデプロイ方法は、主に次の考慮事項に基づいて、DaemonSet を使用してデプロイし、ホスト パスを介してマップし、CSI デプロイメントを選択しません。 1) Alluxio ヒューズの高いパフォーマンスの中核は、データ キャッシュとメタデータ キャッシュにあります
。データ キャッシュ 大量のディスクを消費する必要があり、メタデータ キャッシュは大量のメモリを消費する必要があります。CSI 形式でデプロイされている場合、各コンテナは少量のディスクとメモリのみを Alluxio ヒューズ プロセスに割り当てることができます。

2) モデルのトレーニング中、読み取られるトレーニング データは非常に反復的であるため、各コンテナーが融合プロセスを開始すると、同じマシンが同じファイルの複数のコピーをキャッシュし、ディスクを無駄にする可能性があります。

3) GPU マシンはトレーニング タスクのみを実行するため、リソース解放の問題を考慮せずにヒューズ プロセスを長時間実行できます。

4) ホストパスの展開方法により、マウントポイントを簡単に復元できます。

ここでマウントポイントの復旧について説明しますが、一般的にAlluxioのヒューズコンテナが様々な異常によりハングした場合、ヒューズプロセスを再起動してディレクトリを再マウントしても、業務コンテナ内のマウントポイントも壊れてしまいます。データが失われると業務はデータを読み取れなくなりますが、マウントポイントが復元されていれば、Alluxio ヒューズコンテナ起動後、業務コンテナ内のマウントポイントは自動的に復元されます。このとき業務自体がリトライしていれば、論理的には影響を受けません。Alluxio ヒューズ プロセスのマウント ポイントのリカバリには 2 つの部分が含まれており、1 つはマウント ポイント自体のリカバリ、つまり、ヒューズ プロセスは再起動のたびに同じマウント ポイントにマウントされる必要があり、もう 1 つはクライアント キャッシュのリカバリです。つまり、ローカルにキャッシュされたファイルを Alluxio クラスタから繰り返しプルすることを避けるために、ヒューズ プロセスを再起動するたびに、キャッシュされたデータ ディレクトリが元のディレクトリと一致する必要があります。マウント ポイントのリカバリをサポートするには、CSI で追加の開発が必要ですが、ホスト パスの形式でマッピングされている場合は、ビジネス コンテナ内で HostToContainer が構成されている限り、追加の開発は必要ありません。
ヒューズ プロセスの展開アーキテクチャ図は次のとおりです。

このシナリオでは、Alluxio クラスターは「小規模クラスター ヘビー クライアント」アプローチでデプロイされます。つまり、小規模な Alluxio クラスターはデータ分散のみに提供され、パフォーマンスとキャッシュは Alluxio ヒューズ自体によって保証されます。Alluxio クラスターは、高度な構成のマスターと少数のワーカーを提供するだけで済みます。クラスターの全体的なデプロイメント アーキテクチャは次のとおりです。

この展開モードによれば、3 つの Raft HA マスターと少数のワーカーがヒューズ プロセスの大規模な展開をサポートできます。

4.4 Alluxio ヒューズのチューニング
1 つ目はメタデータ キャッシュです。Alluxio ヒューズはメタデータ キャッシュを有効にできます。これはマスターの UFS メタデータ キャッシュと混同しやすいです。簡単に説明しましょう:

1) Alluxio マスターは UFS メタデータをキャッシュし、メタデータを更新するかどうかはクライアントで設定された alluxio.user.file.metadata.sync.interval によって決定されます。この値が 10 分に設定されている場合、クライアントがマスターを要求したときに、マスターが過去 10 分以内にメタデータを更新していれば、マスターは UFS に最新のメタデータの取得を要求せずに、キャッシュされたメタデータを直接返します。それ以外の場合は、マスターはキャッシュされたメタデータを直接返します。 UFS の最新のメタデータを返し、マスターのメタデータを更新します。

2) ユーザーが Alluxio ヒューズを使用して Alluxio にアクセスする場合、最初にカーネル キャッシュ メタデータが無効かどうか (ヒューズ起動パラメータ attr_timeout、entry_timeout として構成) がチェックされ、次にユーザー スペース メタデータ キャッシュが無効かどうか (alluxio.user として構成) がチェックされます。 .metadata.cache .expiration.time) を確認し、マスター キャッシュが無効かどうかを確認します (alluxio.user.file.metadata.sync.interval として構成)。1 つのレイヤーが無効でない限り、HDFS の最新のメタデータは無効です。得られる。

したがって、ローカル メタデータ キャッシュが失敗するたびにヒューズが UFS の最新のメタデータを取得できるように、ヒューズ メタデータ キャッシュを有効にした後、alluxio.user.file.metadata.sync.interval=0 を設定することをお勧めします。
さらに、fuse のメタデータ キャッシュは、いくつかの特別なコマンドを通じて更新できます (alluxio.fuse.special.command.enabled=true を設定する必要があります)。
マウント ディレクトリが次のコマンドであると仮定すると、メタデータ キャッシュは次のコマンドを通じて強制的に更新できます。 /mnt/alluxio では、次のコマンドを使用してすべてのメタデータ キャッシュを更新します。

 ls -l /mnt/alluxio/.alluxiocli.metadatacache.dropAll

次のコマンドを使用して、指定したディレクトリのメタデータ キャッシュを更新します (ここでは /user/test を例にします)。

ls -l /mnt/alluxio/user/test/.alluxiocli.metadatacache.drop

コード (例として Python を使用) では、メタデータは次のようにクリーンアップできます。

import os
 print(os.path.getsize("/mnt/alluxio/user/test/.alluxiocli.metadatacache.drop"))

ただし、カーネル メタデータ キャッシュはクリアできないことに注意してください。そのため、カーネル メタデータ キャッシュには小さい値 (1 分など) を設定し、ユーザー スペースのメタデータ キャッシュには大きい値 (1 時間など) を設定することをお勧めします。メタデータに整合性要件がある場合は、ユーザー空間メタデータ キャッシュを手動で更新し、カーネル メタデータ キャッシュが無効になるまで待ちます。
メタデータ キャッシュとデータ キャッシュが同時に有効になっている場合、メタデータ キャッシュをクリアするコマンドの使用時にいくつかの問題が発生しますが、参照: #17029 で修正されました。
2 つ目はデータ キャッシュです。Alluxio ヒューズは DeamonSet モードでデプロイされているため、基本的に物理マシンのディスク全体をデータ キャッシュに使用でき、Alluxio ワーカーのトラフィックが大幅に削減されます。
最後はリソースの割り当てです。各マシンにはヒューズ プロセスが 1 つしかないため、より多くの CPU とメモリをヒューズ プロセスに適切に割り当てることができ、突然のリクエストの急増に対処するために CPU を適切に過剰に割り当てることができます。
メモリに関しては、まずヒープ メモリの構成で、ユーザー空間メタデータ キャッシュが有効な場合は、キャッシュ パス数 * 2KB * 2 に応じて Xmx を設定します。さらに、DirectoryMemory はより大きく設定できます。通常は 8G で十分です。カーネル データ キャッシュが有効になっている場合は、コンテナのメモリ使用量の Kubernetes 計算にページキャッシュの使用量が含まれるため、ページキャッシュを保存するコンテナ用のスペースも予約する必要があります。ページキャッシュがコンテナの OOM を引き起こすかどうかについては、多くのドキュメントを検索しましたが、正確な結論は得られませんでしたが、次の構成で圧力テストを実施したところ、コンテナが OOM にならず、ヒューズのパフォーマンスが非常に安定していることがわかりました。

4.5 起動結果
アルゴリズム モデル トレーニングを Alluxio ヒューズに切り替えた後、モデル トレーニングの効率はローカル ディスクのパフォーマンスの 90% に達し、UnionStore のオリジナルの s3fs-fuse マウントと比較して、パフォーマンスは約 250% 向上しました。

5. ビッグデータシナリオにおける S3 プロキシの適用

モデルの立ち上げシナリオを振り返ると、アルゴリズム ビジネスにモデルの読み取りを高速化する機能を提供しただけでなく、オブジェクト ストレージ プロトコルと互換性のあるコンポーネントも生成しましたが、そのダウンロード速度は通常のオブジェクト ストレージよりもはるかに高速でした、つまり Alluxio S3 プロキシなので、「ハンマーで釘を見つける」ようなことができるようになりました。
ここでは、ビッグ データ コンポーネントのリリースとオンライン プロセスを紹介します。フローチャートは大まかに次のとおりです。

言葉で簡単に説明すると次のとおりです。

1) 開発者がコードを変更した後、コードを対応するコンポーネントのマスター ブランチにマージします。このとき、Gitlab は CI の Web フックを呼び出し、CI は対応するコンポーネントのパッケージ化およびコンパイル ロジックを実行します。

2) コンポーネントがバイナリ パッケージにパッケージ化された後、CI はバイナリ パッケージのメタデータを Kosmos に登録し、バイナリ パッケージを Kosmos にアップロードします。Kosmos はバイナリ パッケージを受信した後、それをオブジェクト ストレージにアップロードします。

3) 開発者は、ビッグ データの運用および保守プラットフォームで起動するコンポーネントとコンポーネントのバージョンを選択します。ビッグ データ コンポーネントは、運用環境のサーバー上で展開ロジックを自動的に実行します。

4) デプロイメント ロジックの実行中、Kosmos はコンポーネントのバイナリ パッケージをダウンロードするように要求され、Kosmos は運用環境サーバーがダウンロードするオブジェクト ストレージの読み取り専用リンクを直接返します。

その中でもKosmosは当社が自社開発したパッケージ管理システムであり、その誕生の背景としては、ZhihuにおけるFlinkリアルタイムコンピューティングプラットフォームの進化に加え、当社のビッグデータ運用保守プラットフォームにも対応する興味があれば、Zhihu の Ansible ビッグ データの実践を確認してください。
一方で、このプロセスの最大の問題は、大規模なノードを起動する場合、オブジェクト ストレージからのバイナリ パッケージのダウンロード速度が遅すぎることです。たとえば、すべての DataNode ノードと NodeManager ノードに変更を加えたい場合、各マシンは数百 MB または GB 以上のバイナリ パッケージをダウンロードする必要があります。オブジェクト ストレージのダウンロード速度 20 ~ 30 MB/秒によると、それぞれマシンのダウンロードには約 30 秒かかります。これは展開ロジック全体の約 2/3 を占めます。10,000 個のデータノードに基づいて計算すると、(3 つのコピーのうち 1 つが利用可能になるようにするため) 2 回のローリング再起動ごとに、バイナリ パッケージのダウンロードに費やされる時間は 40 時間以上に達し、展開効率に影響します。
一方、オブジェクト ストレージを異なるコンピュータ ルームで使用すると、外部ネットワーク トラフィックの問題にも直面し、コストが比較的高くなるため、Kosmos はバイナリ パッケージの異なるオブジェクトへのアップロードをサポートするために複数のコンピュータ ルームに変換されました。 Kosmos をリクエストするときは、Kosmos から同じコンピュータ ルーム オブジェクト ストレージのダウンロード リンクを取得するために、リクエストにコンピュータ ルーム パラメータを追加する必要があります。ユーザーが間違ったコンピュータ ルームを選択した場合でも、外部ネットワーク トラフィックは引き続き発生します。使用済み。
上記の問題は実際には、ダウンロードとデプロイメント ロジックを分離し、高い同時実行性でバイナリ パッケージをノードにダウンロードしてからデプロイメントをローリングするなど、ビッグ データの運用および保守プラットフォームを変換することで解決できますが、変換には時間がかかります。現在では、ファイルをダウンロードするより効率的な方法である Alluxio S3 プロキシがあるため、この変換を実行する動機はさらに低くなります。
Kosmos のオブジェクト ストレージを Alluxio にマウントします。Kosmos のダウンロードが要求されると、Alluxio S3 プロキシの読み取り専用リンクが返され、ユーザーが S3 プロキシからデータを読み取ることができます。変更されたフローチャートは次のとおりです:

変換後、Kosmos のほとんどすべてのダウンロード リクエストは 1 ~ 2 秒以内に完了できます。これは、オブジェクト ストレージからダウンロードするよりも 90% 以上高速です。次の図は、本番環境では、Kosmos がオブジェクト ストレージに接続し、Alluxio のダウンロードが行われていることを示しています。速度の比較。Alluxio S3 プロキシは当社により 600MB/秒に制限されています。

さらに、Alluxio は複数のコンピュータ ルームも展開しており、Kosmos のマルチ コンピュータ ルーム ソリューションをサポートしています。ユーザーが間違ったコンピュータ ルームを選択した場合でも、追加の外部ネットワーク トラフィックは発生しません。他のコンピュータ ルームの Alluxio クラスタを要求するだけです。 、一定量の専用回線の帯域幅を消費します。

6. 許可関連

Alluxio が HDFS と連携する場合、HDFS のファイル パーミッション システムを継承するため、HDFS と Alluxio のユーザーが一致しない可能性があり、パーミッションの問題が発生しやすくなります。権限の問題の方が重要なので、別の章を使って紹介します。
コード調査とテストを通じて、Alluxio バージョン 2.9.2 (HDFS と Alluxio は両方とも SIMPLE 認証方式を使用) に基づいてユーザーと権限のマッピング関係をまとめました。

1 つ目は、Alluxio Java クライアントのユーザーです。Alluxio Java クライアントが Alluxio と対話するとき、alluxio.security.login.username が設定されている場合、Alluxio クライアントは設定されているユーザーとして Alluxio クラスターにアクセスします。それ以外の場合は、スタートアップを使用します。 Alluxio Java クライアントのユーザー Alluxio にアクセスします。
Alluxio マスター/ワーカーが HDFS と対話するとき、マスター/ワーカーが起動時に環境変数 HADOOP_USER_NAME (alluxio-env.sh で設定可能) を設定すると、マスター/ワーカーは設定されたユーザーとして HDFS にアクセスします。それ以外の場合は、マスター/ワーカーを使用します。ワーカー プロセスは、ユーザーによる HDFS へのアクセスを開始します。ここで、マスターとワーカーはできるだけ同じ HDFS ユーザーで構成する必要があることに注意してください。そうしないと、権限の問題が確実に発生します。
HDFS にファイルを書き込むとき、Alluxio は最初にマスター/ワーカーによって設定された HDFS ユーザーとしてファイルを書き込み、次に HDFS の chown コマンドを呼び出して、ファイルの所有者を Alluxio Java クライアントのユーザーに変更します。例: Alluxio 起動ユーザーが alluxio で、Alluxio Java クライアント ユーザーが test であると仮定します。HDFS にファイルを書き込むとき、Alluxio は最初に alluxio アカウントを使用してファイルを HDFS に書き込み、次にそのファイルを test ユーザーに書き込みます。このとき、alluxio ユーザーが HDFS スーパーユーザーでない場合、chown 時にエラーが発生し (さらに残念なのは、alluxio がこのエラーをクライアントにスローしないことです)、Alluxio 上で見られるファイルの所有者がテストされることになります。 、しかし、HDFS 上のファイルの所有者は alluxio であるため、データが矛盾しています。
2 番目は S3 プロキシのユーザーです。S3 プロキシは特別な Alluxio Java クライアントでもありますが、同時にサーバー側でもあります。ここで、ユーザーは S3 プロキシの AK SK と HDFS ユーザー間のマッピングを要求します。デフォルトでは、S3 プロキシはユーザーの AK を Alluxio クラスターにアクセスするユーザーにマッピングします。AK を特定のユーザーにマッピングするなど、マッピング関係を自分で実装することもできます。S3 プロキシには関連するプラグインがあります。
最後に、Alluxio Fuse のユーザーへ。Alluxio Fuse には Linux ファイル システムが関与し、Linux ローカル ファイル システムに関連する多くの実装があるため、以前のものよりも複雑です。ここでは、デフォルトの状況である alluxio.fuse についてのみ説明します。 auth .policy.class=alluxio.fuse.auth.LaunchUserGroupAuthPolicy の場合。ユーザーがマウント ディレクトリにアクセスすると、現在の Linux ユーザーが使用されます。ユーザーには、マウント ディレクトリ内のすべてのファイルの所有者が、fuse プロセスを開始したユーザーであることがわかります。fuse がローカル キャッシュ ディレクトリに書き込むときは、そのユーザーが使用されます。さらに、fuse プロセスが Alluxio クラスタと対話するとき、それは Alluxio Java クライアントのロジックに従います。
要約すると、推奨されるユーザー設定方法は次のとおりです。

1) Alluxio クラスターは alluxio アカウントで起動され、alluxio アカウントは HDFS スーパー ユーザーとして設定されます。

2) S3 プロキシは alluxio アカウントで開始され、ユーザーがアクセスすると、AK が HDFS アカウントになります。

3) Alluxio ヒューズは、許可なくローカル データが書き込まれるのを防ぐために root ユーザーとして起動し、allow_other パラメーターを追加し、alluxio.security.login.username を HDFS ユーザーとして設定します。

7. その他の問題

立ち上げプロセス中に多くの問題に遭遇しましたが、そのほとんどは構成項目のチューニングに関連していました。これらの問題の主な理由は、Alluxio が一般的な設計のキャッシュ システムであり、ユーザー シナリオが多様であるため、デフォルトの構成で完全に適応することが難しいためです。たとえば、複数の Alluxio クラスター セットがあり、それぞれのクラスターが問題を解決するためにクラスターが使用されますが、問題が異なるため、これらのクラスターの構成も若干異なります。Alluxio が提供する多くの柔軟な構成のおかげで、ほとんどの問題は構成を変更することで解決できるため、ここでは印象に残ったいくつかの "代表" のみを紹介します。
最大コピー数:モデルの起動シナリオでは、キャッシュされたコピーの数に上限を設定しません。これは、アルゴリズム モデルが読み取られるとき、多くの場合、そのモデルは数十、さらには数百のコンテナーによって読み取られる大規模なモデルであるためです。同時に読み取られるため、ストレージはあまり占有しませんが、読み取り数が多く、今回のみ高い同時実行性で読み取られ、2 回目に読み取られることはほとんどありません。したがって、ここでは各キャッシュ ファイルのコピー数に制限はなく、最大のスループットと最高のパフォーマンスを達成するために、各ワーカーは 1 つのコピーをキャッシュできます。モデルのトレーニング シナリオでは、キャッシュ コピーの数を 3 に設定しました。トレーニング データの量が多く、ストレージを節約する必要がある一方で、Alluxio ヒューズのローカル キャッシュがほとんどのデータを負担します。トラフィックが多いため、ワーカーのスループット要件は比較的高くなります。
S3 プロキシ ListObjects の問題: S3 プロキシが ListObjects リクエストを満たすときに maxkeys パラメータを無視し、多数の不要なディレクトリをリストしていることがわかりました。たとえば、リクエストするプレフィックスが /tmp/b で、maxkeys が 1 の場合、S3 プロキシは /tmp の下にあるすべてのファイルを再帰的にリストし、すべてのファイルからプレフィックス /tmp/b を満たす最初のデータを選択します。これはパフォーマンスが悪いだけでなく、OOM の可能性にもつながります。一時的な解決策を使用して修正します。興味がある場合は、#16926 を参照してください。この問題はより複雑であり、マスターと S3 プロキシが共同で解決する必要がありますが、#16132 の進展に期待できます。
アドレスの競合を監視します。 監視には Prometheus ソリューションを使用します。Alluxio はいくつかのインジケーターを公開しますが、マスターまたはワーカーの起動パラメーターにエージェントとポートを追加することで JVM インジケーターを公開する必要があります。エージェントを追加した後、モニターは起動パラメーターを継承するため、そのため、モニターもマスターとワーカーと同じインジケーター ポートを使用しようとします。これにより、「アドレスはすでに使用されています」エラーが発生し、モニターの起動に失敗します。詳細については、#16657 を参照してください。
マスターが UFS フル メタデータを異常にロードする:パスの下に UFS マウント パスがある場合、このパスで getStatus メソッドが呼び出されると、Alluxio マスターはこのパスの下にあるすべてのファイルのメタデータを再帰的に同期します。たとえば、/a パスの下の /a/b パスは UFS マウント パスであり、getStatus("/a") を呼び出すと、/a の下のメタデータが完全にロードされます。/a が大きなパスである場合、メタデータのロードが多すぎるため、GC が頻繁に発生したり、マスターがスタックしたりする可能性があります。詳細については、#16922 を参照してください。
マスターはアクセス時間を頻繁に更新します:使用中に、マスターが時々スタックすることがわかりました。Alluxio コミュニティの学生仲間の助けを借りて、マスターの頻繁に更新されるファイルの最終アクセス時間が原因である問題を特定しました。 #16981 を組み込むことでこの問題を解決しました。

8. まとめと展望

実は、2022年後半からAlluxioの研究を開始していたのですが、諸事情によりしばらく保留となり、Alluxioの開発が今年にずれ込んでしまいました。私たちの研究と立ち上げの過程において、Alluxio コミュニティは私たちに多くの援助を提供してくれる最も強力な海外援助です。
今回、アルゴリズムの場面で Alluxio をテストしましたが、その結果は非常に驚くべきものでした。
パフォーマンス面では、アルゴリズムモデルを起動するシーンではUnionStoreをAlluxioに置き換えることで最大数十倍のパフォーマンス向上を実現しており、モデルトレーニングシーンではAlluxioヒューズのローカルデータキャッシュと連携しています。同様のローカル NVME ディスクを実現するには、UnionStore + s3fs-fuse のソリューションと比較して、パフォーマンスが 2 ~ 3 倍向上します。
安定性の面では、HDFS の変動やバージョンアップ、マスターカットなどが発生した場合でも、Alluxio はデータキャッシュとメタデータキャッシュにより、一定期間影響を受けることなく正常にサービスを提供できます。
コストの点では、Alluxio は UnionStore と比較して毎年数十万リアルマネーを節約しており、パフォーマンスには依然として余裕があります。
長期的な開発の観点から見ると、Alluxio は強力なスケーラビリティを備えており、特に Alluxio の新世代アーキテクチャ Dora は、大規模で小さなファイルのキャッシュに対する需要をサポートできるため、今後の人工知能の波に直面するアルゴリズム チームのサポートに自信が持てるようになります。 。
最後に、立ち上げ時に多くの支援と提案を提供してくれた Alluxio チームに改めて感謝したいと思います。また、ビッグ データ OLAP クエリ アクセラレーション シナリオと分散型データの分野で引き続き協力し、深くコミュニケーションできることを願っています。データセットのオーケストレーション。

【事例2:アリ】アントグループの大規模研修におけるAlluxioの活用

1. 背景の紹介

まず、Alluxio を導入した理由ですが、実際、私たちが直面している問題は業界の問題と基本的に同じです。

  • 1 つ目は、ストレージ IO のパフォーマンスの問題です。現在、GPU のモデル トレーニング速度はますます高速になっており、基盤となるストレージに一定の圧力がかかることは避けられません。基盤となるストレージが現在の GPU のトレーニング速度をサポートできない場合、モデルのトレーニングの効率が大幅に制限されてしまいます。
  • 2 つ目は 1 台のマシンの保管容量ですが、現在モデルコレクションはますます大きくなり、1 台のマシンを保管しきれないという問題が必然的に発生します。では、この種の大規模モデルのトレーニングをどのようにサポートすればよいのでしょうか?
  • 3 番目は、ネットワーク遅延の問題です。現在、多くのストレージ ソリューションがありますが、高スループット、高同時実行性、低レイテンシのパフォーマンスを兼ね備えたソリューションはありません。Alluxio は一連のソリューションを提供します。Alluxio と比較して小型化されています。すぐに使用でき、コンピュータと同じコンピュータ ルームに展開できるため、ネットワークの遅延とパフォーマンスの損失を最小限に抑えることができます。主にこの理由から、Alluxio を Ant Group に導入することにしました。

共有の中心的な内容は次のとおりです。合計 3 つの部分に分かれています。つまり、Alluxio が Ant Group に導入された後、主に次の 3 つの側面からパフォーマンスの最適化を実行しました。最初の部分は安定性の構築、 2 番目の部分はパフォーマンスの最適化であり、3 番目の部分はスケールアップです。

2. 安定構造

まず、安定性を構築する必要がある理由を紹介します。リソースが k8s によってスケジュールされ、リソースの再起動や移行が頻繁に行われる場合、頻繁な FO クラスターに直面する必要があり、FO のパフォーマンスがそのままパフォーマンスに反映されます。経験の観点から言えば、FO 時間が 2 分間利用できない場合、ユーザーには大量のエラー レポートが表示される可能性があります。数時間利用できない場合は、ユーザーのモデル トレーニングが直接強制終了される可能性があるため、安定性の構築が最も重要です。重要 最も重要なことは、私たちが行う最適化は主に 2 つの部分から実行されます。1 つはワーカー レジスタ フォロワーで、もう 1 つはマスターの移行です。
1. ワーカー登録フォロワー

最初にこの問題の背景を紹介します: 上の図は、Alluxio 操作の安定した状態を示しています。マスターはメタデータ サービスを実行し、次に raft を通じてメタデータの一貫性を内部的に同期し、プライマリを通じて外部にメタデータ サービスを提供し、次にノードが提供するワーカーを通じてメタデータ サービスを提供します。この 2 つの間では、ワーカー登録プライマリ、つまりワーカー ノードの検出を通じて検出が行われるため、ワーカー ノードが安定した状態で実行されることが保証されます。この時点でプライマリが再起動された場合、次のプロセスである FO 移行が必要です。たとえば、この時点でプライマリが再起動された場合、内部スタンバイは raft を通じて再選出される必要があります。選出前に、実際、プライマリのメタデータはワーカーから切断されています。切断状態では、フェイルオーバーを実行するには、一貫した Raft の選択が必要です。次に、マシンが新しいプライマリを選択した場合、この時点で作業を完了する必要があります。再検出。検出がプライマリに登録された後、新しいプライマリがメタデータ サービスを外部に提供し、ワーカーがデータ データ サービスを外部に提供して障害転送が完了すると、問題が発生します。障害 FO を実行するとき、ワーカーは新しいプライマリを検出した後に再登録する必要があります。この部分では主に 3 つの問題に直面しています。1 つ目は、最初のワーカーが回復したばかりなので、最初のワーカーが登録される前にクラスターが利用できないことです。
新しいプライマリリーダーシップ機能を備えていますが、現時点でワーカーがいない場合、実際にはプライマリ全体にデータ ノードがありません。つまり、メタデータのみにアクセスでき、データにはアクセスできません。
2 つ目は、すべてのワーカーの登録プロセス中のパフォーマンスに対するコールド データの影響です。最初のワーカーが に登録すると、データ ノードが存在するため、この時点で外部にサービスを提供できます。また、後続の登録のプロセスでは、最初のノードが に登録し、後続のノードが登録時に、ユーザーがアクセスする際、worker2 がブロックをキャッシュすると、worker2 はミス状態になります。このとき、データは失われます。既存のワーカーの中から最下層にファイルを読み込む人が選出されます。ファイルを読み込んだ後、再び外部サービスを提供しますが、その読み取りプロセス中、たとえば、worker1 が ufs を読み込むとき、これにはウォームアップ プロセスが含まれるため、パフォーマンスが低下します。これが登録の問題です。
3つ目は、作業者登録完了後のデータ冗長化クリーニングの問題です。実は、登録完了後、登録処理中に少量のデータが再加熱され続けるという問題があり、すべてのワーカーが登録された後、登録処理中に再キャッシュされたデータが冗長性を引き起こすため、処理する必要があります。クリーンアップ。この重大度レベルによると、最初のワーカーが登録されるまでクラスターは使用できなくなります。ワーカーのサイズが比較的小さい場合、登録時間は 2 ~ 5 分で、クラスターは 2 分以内に使用できなくなる可能性があります-5 分。多数のエラーが報告されます。ワーカーのサイズが比較的大きい場合 (ボリュームが数テラバイトのディスクなど)、完全に登録するまでに数時間かかります。そうなると、クラスタ全体が数時間外部サービスを提供できなくなり、ユーザーから見るとクラスタが不安定になるため、この部分を最適化する必要があります。
現在の最適化計画は、すべてのワーカーをすべてのマスターに登録し、事前に登録し、ワーカーが起動したらすぐにすべてのマスターに再登録し、その後、途中でこのリアルタイム ハートビートを通じてワーカーのステータスを更新し続けることです。では、この最適化の効果は何でしょうか? 以下の写真をご覧ください。

現時点で、予備選挙が再開された場合、内部選挙はラフトを通じて実施され、新たに選出された予備選挙は外部の世界にサービスを提供します。予備選挙はいくつかの部分を経る必要があります。再起動すると、raft は自己検出を実行します。選挙後、新しい予備選挙は追いつかれて外部の世界にサービスを提供でき、登録用の労働者を再獲得する必要がないため、時間を完全に節約でき、必要なのは3 つのステップ: 自己発見、選択、キャッチアップ。
このソリューションは非常に効率的で、30 秒以内に完了できるため、FO 時間が大幅に短縮されます。別のレベルでは、いくつかの悪影響もあります。主な理由は、マスターの 1 つが再起動されると、プライマリは通常のサービスを外部に提供できるようになり、スタンバイが再起動すると、ワーカーが外部にサービスを提供することです。また、このブロックのメタデータ情報を再登録する必要があります。実際、このブロックのメタデータ情報のトラフィックは非常に大きいです。このとき、現在のワーカーに一定の影響を及ぼします。登録されている一部のマスターのパフォーマンスに影響を与える場合がありますが、今回はクラスターの負荷がさほど高くなければ完全に無視できるため、この最適化を行います。
2. マスターの移行

図に示すように、実際には、最初は 3 つのマスターが外部にサービスを提供しており、これら 3 つのマスターが安定した状態に達すると、ワーカーがプライマリに登録され、外部にサービスを提供します。スタンバイ 2 を置き換え、新しいプライマリが古いプライマリを置き換えます。この時点で、新しいマスター クラスター ノードはスタンバイ 3、スタンバイ 4、新しいプライマリの 3 つで構成されます。通常のプロセスに従います。このワーカーは接続を確立する必要があると言われました。現在の新しいクラスターでは、通常のハートビートを維持し、外部サービスを提供しますが、現時点ではそうではありません。主な理由は、ワーカーによって認識されるマスター情報が、実際には最初にコンフィギュレーターによって静的に実行されるためです。注入され、これは初期化中に書き込まれており、バックグラウンドは動的更新なしで静的に管理されるため、これら 3 つのノードは決して認識されず、古い 3 つのノードは常に認識されます。これは、クラスター全体を直接ハングアップするこのシナリオと同等です。外部データノードが存在しない場合、サービスを提供できません 復旧方法は主に、手動で 3 つの新しいノードをコンフィギュレーションに登録し、ワーカーを再起動して識別する必要があります この時点でクラスターが比較的規模が大きい場合規模が大きく、ワーカー ノードの数が比較的多い場合、現時点での運用と保守のコストが非常に高くなります。これが、私たちが直面しているマスター移行の問題です。次に、この安定性に対処する方法を見てみましょう。
私たちのソリューションは、プライマリとワーカーの間のメイン ハートビートを維持することです。マスター ノードが変更されると、マスター ノードのリアルタイム更新を実現するために、メイン ハートビートを介して現在のワーカーが同期されます。たとえば、standby1 がstandby3 に置き換えられます。時間になると、プライマリはメイン ハートビートを通じて現在の 3 つのノード (プライマリ、スタンバイ 2、スタンバイ 3) を現在のワーカーに同期します。この時点では、ワーカーが最新です。スタンバイ 4 とスタンバイ 2 を置き換えると、3 つのノード間の状態は次のようになります。現時点では変更されています。同期して最新の状態に保ちます。次に新しいプライマリを追加する場合は、4 つを同期し、再起動して選出を実行します。選出後、これが新しいプライマリになります。ワーカーの最後のステップのため、ノード これら 4 つのノードが保存されており、これら 4 つのノードの中から現在のリーダーを見つけて、新しいプライマリを特定し、3 つの新しいマスターを同期して安全な反復プロセスを実現すると便利です。リソーススケジューリングにより移動するため、安定して移動できます。以上の2部が安定構築の内容となります。

3. パフォーマンスの最適化

パフォーマンスの最適化のために、主にフォロワーの読み取り専用の処理を実行しました まず、図に示すような背景を説明します。

これが現在の Alluxio の全体的な枠組みであり、まずクライアントがリーダーからメタデータを取得し、そのメタデータに従って通常のワーカーにアクセスし、リーダーとスタンバイが raft を介してメタデータの整合性をとりながら同期し、リーダーがメタデータを同期するという流れになります。リーダーによってのみ開始され、その後スタンバイに同期されるため、シーケンスが存在します。スタンバイは、新しい情報を開始してリーダーと同期することができません。これは、データの一貫性の原則に違反する問題です。
もう 1 つの部分は、現在のスタンバイが以前のワーカー レジスタ フォロワーによって最適化された後、実際にはスタンバイとワーカーの間に特定の接続が存在し、データが収集されるため、スタンバイはすでにリーダーの属性を持っています。データの整合性の観点から言えば、データは基本的にリーダーと一致しています。
そして、この部分がバックアップとして、つまり安定性のバックアップとして使用される場合、実際にはリソースの無駄になります。使用したいのですが、raft データの一貫性のルールを破ることはできません。この場合、試してみます。読み取り専用サービスを提供できるかどうか。読み取り専用サービスはraftのジャーナルエントリを更新する必要がなく、一貫性に影響を与えないため、スタンバイのパフォーマンスを最大限に活用できるため、いくつかの最適化されたソリューションが考えられます。ここには、ビジネス シナリオも含まれます。つまり、シナリオがモデルのトレーニングまたはファイル キャッシュの高速化に適している場合、データは最初のウォームアップ中にのみ書き込まれ、その後のデータは読み取り専用になります。多数の読み取り専用シナリオでは、スタンバイ ペアが使用されます。クラスター全体のパフォーマンスの向上は非常に印象的です。

図に示すように、詳細な最適化スキームは次のとおりです。

主に前回の概要に基づいています。すべてのワーカーがすべてのスタンバイに登録されています。このとき、スタンバイとプライマリのデータは基本的に同じです。他の部分は、プライマリとワーカーの間で維持されるメインのハートビートです。この時点で、スタンバイとプライマリのデータは基本的に同じです。クライアントが読み取り専用リクエストを開始すると、処理のために現在のすべてのマスターにランダムにハッシュされます。処理が完了すると、クライアントに戻り、書き込みリクエストは依然としてクライアントに発行されます。主要な。そして、Raft の整合性を崩さないことを前提として、読み取り専用のパフォーマンスを向上させることができ、このマシンを拡張すると、通常の論理で拡張した場合の 3 倍以上の読み取り専用のパフォーマンスに達する可能性があります。フォロワーの読み取り結果も同様です。これは、Alluxio 導入後のパフォーマンスの最適化です。

4. スケールアップ

規模の改善は主に水平方向の拡大ですが、まず、この問題の背景を図に示します。

これは依然として Alluxio のフレームワークです。マスターには主に多くのコンポーネント要素が含まれています。最初はブロック マスター、2 番目はファイル マスター、そしてラフトとスナップショットがあります。この部分の主な影響要因は次の 4 つの側面です:

  • Bblock マスターで大規模なクラスターを作成する場合、ブロック マスターが直面するボトルネックはメモリです。メモリは大量のマスター メモリ (主に格納されたワーカー ブロック情報) を占有します。
  • ファイル マスターは主に i ノード情報を保存します。大規模なシナリオの場合、ローカル ストレージへの負担が非常に大きくなります。
  • Raft が直面する同期効率の問題。
  • スナップショットの効率が追いつかない場合、バックグラウンドで大量のジャーナル エントリが存在し、パフォーマンスの向上にも一定の影響を与えることがわかります。

いくつかのテストを行った結果、大規模なシナリオでは、マシンの仕様がそれほど大きくなければ、3 億から 6 億の規模をサポートできますが、10 億、さらには数百億の規模をサポートしたい場合は、ストレージマシンを拡張する必要がある モデルトレーニングの規模は無限に大きくなる可能性があるため、仕様は非現実的ですが、マシンの仕様は無限に拡張することはできません。では、この問題をどのように最適化すればよいでしょうか?

この最適化では、主に Redis の実装スキームを参照します。つまり、最下位層でメタデータを断片化し、複数のクラスターで外部サービスを提供できます。この利点の 1 つは、全体を外部に提供できることです。複数のクラスターをユーザー自身が完全に制御し、各クラスターに異なるデータを割り当てるなどの最適化戦略を採用することもできますが、これはユーザーへの負担が大きくなります。まずこのフレームワークを紹介します. まず, メタデータをセグメント化します. たとえば, ユーザーが取得したデータセット全体は大きすぎて 1 つのクラスターに収まりません. このとき, 大規模なデータセットはセグメント化されます.メタデータのハッシュ(Hash)マッピング、および特定のハッシュ値をシャードの 1 つにマッピングすることで、クラスターの小さなクラスターは、キーの対応する部分に対応するファイルをキャッシュするだけで済み、ターゲットが存在できるようになります。クラスター上で性的選択をします。
その後、他のデータは他のクラスター用に予約され、設定されたクラスター サイズに全量のハッシュが割り当てられるため、大規模なモデルのトレーニング ファイル全体を複数のシャードにキャッシュし、大規模なデータを提供できます。モデルを外部でトレーニングし、フロントエンドにプロキシを追加します。プロキシは実際に内部でハッシュ マッピング テーブルを保持します。ユーザーからのリクエストは実際にプロキシを介してハッシュ マッピングによって検索され、固定クラスタに割り当てられます。たとえば、ファイル リクエストのハッシュ マッピングを計算することで、ハッシュ マッピングがクラスタ 1 にルーティングされることがわかります。このようにして、クラスタ 1 が責任を負い、他のキーのマッピングが他のクラスタに割り当てられて中断されます。データをアップします。これには多くの利点があります。

  • 1 つ目は、メタデータの保持容量が大きくなったことです。
  • 2 つ目は、リクエストの圧力を複数のクラスターに分散することで、全体的な QPS 機能とクラスターのスループットがそれに応じて向上します。
  • 3つ目は、このスキームにより、理論的には多くのクラスターを拡張できるということです。単一クラスターが3億から6億の規模をサポートする場合、3つのクラスターでサポートされる規模は9億から18億です。さらに拡張する場合は、数百億規模のサポートソリューション。

上記は、モデルに対して行ったいくつかの最適化です。全体のフレームワークには、安定性の構築、パフォーマンスの最適化、スケールの改善が含まれます。

  • 安定構築の観点:クラスタ全体の FO 時間を 30 秒以内に制御でき、クライアント側のメタデータ キャッシュ機構など他の機構と連携すれば、ユーザーが意識することなく FO を実現できます。実はユーザーが一番望んでいることを認識することなく、最下層で行われた作業を全て復元できるので、業務研修が中断されることもなく、ミスを感じることもなく、よりユーザーに優しい方法です。
  • パフォーマンスの最適化に関して:単一クラスターのスループットが 3 倍以上向上し、全体的なパフォーマンスも向上するため、より多くの同時モデル トレーニング タスクをサポートできるようになります。
  • モデル スケールの改善の観点から言えば、モデル トレーニング セットはますます大きくなり、外部サポートを提供するためにこの種のモデル トレーニングを導入することができます。

Alluxio がこれらの最適化を適応させるためにアリを導入した後、実行後のビジネスのあらゆる方向へのサポート効果は比較的明らかです。さらに、現在私たちはオープンソース コミュニティと多くの協力を行っており、コミュニティも私たちに多くの支援を提供しており、たとえば、いくつかの解決策を提供したり、いくつかの緊急の問題について支援したりすることができます。ここに感謝の意を表します!

【事例3:Microsoft】大規模ディープラーニング学習向けキャッシュ最適化実践

共有ゲスト: Zhang Qianxi-Microsoft シニア R&D エンジニア

ガイド

近年、ディープラーニングの台頭により、Alluxio 分散キャッシュ テクノロジーがクラウド上の IO パフォーマンスの問題を解決する業界の主流ソリューションになりつつあります。それだけでなく、Alluxio はデータ レイクに必要な統合管理機能とアクセス機能も当然備えています。この記事では、大規模な深層学習トレーニングのためのキャッシュの最適化について共有し、主に今日の大規模な深層学習トレーニングのストレージ状況と課題を分析し、深層学習トレーニングにおけるキャッシュ データ配置の適用について説明し、大規模な深層学習のリソース割り当てとスケジューリングを紹介します。大規模なキャッシュ システム。

1. プロジェクトの背景とキャッシュ戦略

まず、関連する背景を共有させてください。

近年、AIトレーニングアプリケーションはますます普及しています。インフラストラクチャの観点から見ると、ビッグ データであれ AI トレーニング クラスターであれ、そのほとんどはストレージとコンピューティングを分離したアーキテクチャを使用しています。たとえば、多くの GPU アレイが大規模なコンピューティング クラスターに配置され、もう 1 つのクラスターはストレージです。Microsoft の Azure や Amazon の S3 などのクラウド ストレージが使用される場合もあります。このようなインフラストラクチャの特徴は、まず、コンピューティング クラスター内に非常に高価な GPU が多数存在し、各 GPU が SSD などの数十テラバイトのストレージなど、一定量のローカル ストレージを備えていることが多いことです。このようなマシンの配列では、リモートエンドの接続に高速ネットワークが使用されることが多く、たとえば、Coco、image net、YouTube 8M などの非常に大規模な学習データがネットワークで接続されます。

上図のように、次のAI学習ではデータがボトルネックになる可能性があります。AI アプリケーションの普及に伴い、データセットが増大し、より多くのトレーニング データが蓄積されていることが観察されています。同時に、GPU トラックは非常に官能的です。たとえば、AMD や TPU などのメーカーは、ハードウェアとソフトウェアの最適化に多大なエネルギーを費やし、GPU や TPU などのアクセラレータをますます高速化してきました。社内でアクセラレータが広く適用されているため、クラスタの導入はますます大規模になっています。ここの 2 つの表は、データセットと GPU 速度のいくつかのバリエーションを示しています。以前のK80からV100、P100、A100と速度が非常に速くなりました。しかし、GPU が高速になるにつれて、GPU の価格も高くなります。IO 速度が GPU の速度に追いつくことができるかどうかなど、私たちのデータは大きな課題です。

上の図に示すように、多くの大企業のアプリケーションでは、リモート データを読み取るときに GPU がアイドル状態になるという現象が観察されています。GPU はリモート データの読み取りを待機しているため、IO がボトルネックになり、高価な GPU が無駄になります。このボトルネックを軽減するために最適化のために多くの作業が行われており、キャッシュは最も重要な最適化の方向性の 1 つです。ここでは 2 つの方法を説明します。

まず、多くのアプリケーション シナリオ、特に K8s と Docker などの基本的な AI トレーニング アーキテクチャでは、大量のローカル ディスクが使用されます。前の記事で述べたように、GPU マシンには一定量のローカル ストレージがあり、ローカル ディスクを使用してキャッシュを実行し、最初にデータをキャッシュすることができます。GPUのDockerを起動したら、すぐにGPUのAIトレーニングを開始するのではなく、まずデータをダウンロードしたり、リモートエンドからDocker内部にデータをダウンロードしたり、マウントしたりすることになります。Docker 内にダウンロードした後、トレーニングを開始します。このようにして、可能な限り、後続のトレーニング データの読み取りをローカル データの読み取りに変換できます。ローカル IO のパフォーマンスは、現時点では GPU トレーニングをサポートするのに十分です。VLDB 2020 には、データ キャッシュ用の DALI に基づく CoorDL という論文があります。このアプローチは多くの問題も引き起こしました。まず、ローカル領域が限られているため、キャッシュされるデータも限られており、データセットがますます大きくなると、すべてのデータをキャッシュすることが困難になります。さらに、AI シナリオとビッグ データ シナリオの大きな違いは、AI シナリオのデータ セットが比較的限定されていることです。多数のテーブルとさまざまなビジネスが存在するビッグ データ シナリオとは異なり、各ビジネス データ テーブルの内容は大きく異なります。AI シナリオでは、データセットの規模と数はビッグデータ シナリオよりもはるかに小さくなります。そのため、社内で提出された多くのタスクが同じデータを読み込むことがよくあります。全員がデータをローカルにダウンロードした場合、データを共有することはできず、データの多数のコピーがローカル マシンに繰り返し保存されることになります。この方法には明らかに多くの問題があり、効率も十分ではありません。

次に 2 番目の方法を紹介します。ローカル ストレージがあまり良くないので、Alluxio のような分散キャッシュを使用して今の問題を軽減できますか? 分散キャッシュはデータをロードするための非常に大きな容量を持っています。さらに、Alluxio は分散キャッシュなので、共有が簡単です。データは Alluxio にダウンロードされ、他のクライアントもキャッシュからこのデータを読み取ることができます。この観点から見ると、Alluxio を使用すると、上記の問題を簡単に解決でき、AI トレーニングのパフォーマンスを大幅に向上させることができます。FAST2020 で Microsoft India Research Institute が発表した Quiver という名前の論文では、そのようなソリューションについて言及しています。しかし、私たちの分析では、このような一見完璧な割り当てスキームは比較的静的であり、効率的ではないことがわかりました。同時に、どのようなキャッシュ削除アルゴリズムを使用するかについても議論に値する問題です。

上図にあるように、AlluxioをAI学習用のキャッシュとして利用するアプリケーションです。K8s を使用して、クラスター タスク全体をスケジュールし、GPU、CPU、メモリなどのリソースを管理します。ユーザーが K8s にタスクを送信すると、K8s はまず、Alluxio マスターにデータのこの部分をダウンロードするように通知するプラグインを作成します。つまり、最初にウォームアップを行い、ジョブに必要なタスクをいくつかキャッシュしてみます。もちろん、Alluxio は持っているだけのデータを使用するため、完全にキャッシュする必要はありません。残りについては、まだキャッシュされていない場合は、リモート エンドから読み取られます。さらに、Alluxio マスターはそのようなコマンドを受信した後、スケジュールされたワーカーをリモート エンドに送信できます。それはクラウド ストレージである場合もあれば、Hadoop クラスターがダウンロードしているデータである場合もあります。この時点で、K8s は GPU クラスターへのジョブもスケジュールします。たとえば、上の図では、このようなクラスターでは、最初のノードと 3 番目のノードを選択してトレーニング タスクを開始します。トレーニング タスクを開始した後、データを読み取る必要があります。PyTorchやTensorflowといった現在主流のフレームワークでも、Prefetch、つまりデータの先読みを行う機能が組み込まれています。事前にキャッシュされた Alluxio のキャッシュ データを読み取り、トレーニング データの IO をサポートします。もちろん、一部のデータが読み取られていないことが判明した場合、Alluxio はリモートからそのデータを読み取ることもできます。Alluxio は統合インターフェイスとして優れています。同時に、ジョブ間でデータを共有することもできます。

上の図に示すように、たとえば、別の人が同じデータで別のジョブを送信し、同じデータセットを利用する場合、そのジョブが K8s に送信されると、Alluxio はデータのこの部分がすでに存在していることを認識します。Alluxio がさらに改善したい場合は、データがどのマシンに送信されるかを知ることもできます。たとえば、この時点では、ノード 1、ノード 3、およびノー​​ド 4 にスケジュールされます。ノード 4 のデータは、いくつかのコピーを作成することでコピーすることもできます。このようにして、すべてのデータは、Alluxio 内であっても、複数のマシン間で読み取られる必要はなく、ローカルで読み取られます。つまり、Alluxio は AI トレーニングにおける IO 問題を大幅に軽減し、最適化したようです。しかし、よく見てみると 2 つの問題があることがわかります。

最初の問題は、AI シナリオではデータへのアクセス モードが以前とは大きく異なるため、キャッシュ削除アルゴリズムが非常に非効率であるということです。2 番目の問題は、リソースとしてのキャッシュが帯域幅 (つまり、リモート ストレージの読み取り速度) と相反する関係にあることです。キャッシュが大きい場合、リモート エンドからデータを読み取る可能性は低くなります。キャッシュが小さい場合、リモート側から大量のデータを読み取る必要があります。これらのリソースをどのようにスケジュールして適切に割り当てるかも考慮する必要がある問題です。

キャッシュ削除アルゴリズムについて説明する前に、AI トレーニングにおけるデータ アクセス プロセスを見てみましょう。AI のトレーニングでは、多くのエポックに分割され、反復的にトレーニングされます。トレーニング エポックごとに、各データが 1 回だけ読み取られます。トレーニングの過学習を防ぐため、各エポックが終了すると、次のエポックでは読み取り順序が変更され、シャッフルが実行されます。つまり、エポックごとにすべてのデータが 1 回読み取られますが、順序は異なります。Alluxio のデフォルトの LRU 除去アルゴリズムは、明らかに AI トレーニング シナリオにうまく適用できません。LRU はキャッシュの局所性を使用するためです。局所性は 2 つの側面に分けられ、1 つは時間局所性、つまり現在アクセスされているデータはすぐにアクセスされる可能性があることです。これはAIトレーニングには存在しません。なぜなら、現在アクセスされているデータは次のラウンドでのみアクセスされ、次のラウンドでもアクセスされるからです。他のデータよりもアクセスしやすい可能性は特にありません。もう 1 つの側面は、データの局所性と空間的な局所性です。つまり、Alluxio が比較的大きなブロックでデータをキャッシュするのは、あるデータを読み込むと、周囲のデータも読み込まれる可能性があるためです。たとえば、ビッグ データのシナリオでは、OLAP アプリケーションがテーブルをスキャンすることがよくあります。これは、周囲のデータがすぐにアクセスされることを意味します。ただし、AI トレーニング シナリオには適用できません。毎回シャッフルするため、それぞれの読み上げ順序が異なります。したがって、LRU の消去アルゴリズムは AI トレーニング シナリオには適していません。

LRU だけでなく、LFU などの主流の消去アルゴリズムにもこのような問題があります。AI トレーニング全体がデータに非常に平等にアクセスできるためです。したがって、データの一部がキャッシュされ、移動されることがない限り、最も単純なキャッシュ アルゴリズムを使用できます。ジョブが到着すると、常にデータの一部のみがキャッシュされます。決してノックアウトしないでください。消去アルゴリズムは必要ありません。これはおそらく最高の除去メカニズムです。上の例のように。上記は LRU アルゴリズムであり、以下は同等の方法です。最初は 2 つのデータのみをキャッシュできます。問題をもっと単純化してみると、容量は2つしかなく、DとBの2つのデータがキャッシュされており、アクセス順序は途中です。例えば最初にヒットするアクセスがBで、LRUであればBが存在するキャッシュがヒットします。次のアクセスは C ですが、C は D と B のキャッシュ LRU にないため、LRU 戦略に基づいて D が置き換えられ、C は保持されます。つまり、この時のキャッシュはCとBです。次に訪れるのはAですが、これもCとBにはありません。したがって、B は削除され、C と A に置き換えられます。次は D ですが、これもキャッシュにないため、D と A が置き換えられます。類推すると、後続のアクセスはすべてキャッシュにヒットしなくなることがわかります。その理由は、LRU キャッシュ中に置き換えられるためですが、エポック内で一度アクセスされており、このエポック内で再度アクセスされることはありません。代わりに LRU がそれをキャッシュしますが、LRU は問題を解決するどころか悪化させます。以下のような方法で統一した方が良いでしょう。次の統一メソッドでは、D と B は常にキャッシュにキャッシュされ、置換は実行されません。このような場合、少なくとも 50% のヒット率が得られます。したがって、LRU や LFU などのアルゴリズムを使用せず、均一なアルゴリズムを使用する限り、キャッシュ アルゴリズムはそれほど複雑である必要はないことがわかります。

2 番目の質問は、キャッシュとリモート帯域幅の関係についてです。現在、すべての主流の AI フレームワークには、GPU がデータを待機するのを防ぐためのデータ事前読み取り機能が組み込まれています。したがって、GPU がトレーニングしているときは、実際に CPU をトリガーして、次のラウンドで使用される可能性のあるデータをプリフェッチします。このようにして、GPU の計算能力を最大限に活用できます。しかし、リモート ストレージ IO がボトルネックになると、GPU が CPU を待たなければならないことになります。したがって、GPU のアイドル時間が長くなり、リソースが無駄になります。IO の問題を軽減するための、より良いスケジュール管理方法が存在することを願っています。

キャッシュとリモート IO は、ジョブ全体のスループットに大きな影響を与えます。したがって、GPU、CPU、メモリに加えて、キャッシュとネットワークもスケジュールする必要があります。Hadoop、yarn、マイソース、K8sなど、これまでのビッグデータの開発プロセスでは、主にCPU、メモリ、GPUがディスパッチされていました。ネットワーク、特にキャッシュ制御があまり良くありません。したがって、AI シナリオでは、クラスター全体の最適化を達成するために、AI を適切にスケジュールし、割り当てる必要があると考えています。

2. SiloD フレームワーク

このような記事は、コンピューティング リソースとストレージ リソースをスケジュールするための統合フレームワークである EuroSys 2023 で公開されました。

全体的な構造は上の図に示されています。左下隅は、クラスター内の CPU および GPU ハードウェア コンピューティング リソースと、NFS、クラウド ストレージ HDFS などのストレージ リソースです。上位層には TensorFlow や PyTorch などの AI 学習フレームワークがいくつかあります。コンピューティングとストレージのリソースを一元的に管理・割り当てするためのプラグインを追加する必要があると考えています。これが私たちが提案する SiloD です。

上図に示すように、ジョブがどのようなスループットとパフォーマンスを達成できるかは、GPU と IO の最小値によって決まります。リモート IO の使用量、リモート ネットワークの使用量。アクセス速度はこのような計算式で求めることができます。ジョブ速度にはキャッシュ ミス率 (1-c/d) が乗算されます。ここで、c はキャッシュのサイズ、d はデータセットです。これは、データが IO がボトルネックになる可能性のみを考慮している場合、おおよそのスループットは (b/(1-c/d)) に等しいことを意味します。ここで、b はリモート エンドの帯域幅です。上記の 3 つの計算式を組み合わせると、右側の計算式、つまりジョブが最終的にどのようなパフォーマンスを達成したいかを推定できます。この計算式を使用して、IO ボトルネックがない場合のパフォーマンスと、IO ボトルネックがある場合のパフォーマンスを計算できます。 IO ボトルネックです。2 分ほどお時間をください。

上記の式を取得した後、それを微分してキャッシュの有効性、つまりキャッシュ効率を取得します。つまり、ジョブがたくさんあるにもかかわらず、キャッシュを割り当てるときにそれらを同等に扱うことができません。ジョブごとに、データ セットと速度に応じて、キャッシュ割り当ての量は非常に異なります。以下に例を示します。この式を例に挙げると、ジョブが非常に高速であることが判明した場合、非常に高速にトレーニングでき、データセットが小さいため、より大きなキャッシュが割り当てられ、メリットが大きくなります。 。

上記の観察に基づいて、SiloD を使用してキャッシュとネットワークを割り当てることができます。さらに、キャッシュのサイズは、各ジョブの速度とデータセット全体のサイズに応じて割り当てられます。ウェブについても同様です。全体のアーキテクチャは次のようになります。K8 のような主流のジョブ スケジューリングに加えて、データ管理もあります。図の左側のキャッシュ管理などでは、クラスタ全体に割り当てられたキャッシュのサイズ、各ジョブのキャッシュのサイズ、各ジョブが使用するリモートIOのサイズをカウントまたは監視する必要があります。次のジョブは Alluxio メソッドに非常に似ており、すべてデータ トレーニングに API を使用できます。各ワーカーはキャッシュを使用してローカル ジョブをサポートします。もちろん、クラスター内のノード間で共有することもできます。

予備的なテストと実験の結果、このような割り当て方法により、クラスター全体の使用率とスループットが大幅に向上し、パフォーマンスが最大 8 倍向上することがわかりました。これにより、ジョブの待機状態や GPU のアイドル状態が明らかに軽減されます。

上記の紹介を要約すると、
まず、AI またはディープ ラーニングのトレーニング シナリオでは、LRU や LFU などの従来のキャッシュ戦略は適切ではなく、uniform を直接使用することをお勧めします。
次に、キャッシュとリモート帯域幅は、全体的なパフォーマンスにおいて非常に大きな役割を果たすペアのパートナーです。
第三に、K8 や Yarn などの主流のスケジューリング フレームワークは、SiloD から簡単に継承できます。
最後に、この論文ではいくつかの実験を行いましたが、さまざまなスケジューリング戦略によりスループットが大幅に向上する可能性があります。

3. 分散キャッシュ戦略とコピー管理

オープンソースの作業もいくつか行いました。分散キャッシュ戦略とレプリカ管理の取り組みはコミュニティに提出され、現在 PR 段階にあります。Alluxio マスターは主に Meta とワーカー クラスター全体を管理します。実際にデータをキャッシュするのはワーカーです。データをキャッシュするブロック単位には多数のブロックが存在します。1 つの問題は、現在のキャッシュ戦略が単一のワーカーを対象としているため、ワーカー内の各データを削除するかどうかを計算する場合、ローカライズされた 1 つのワーカーでのみ計算する必要があることです。

上の例に示すように、ワーカー 1 にブロック A、ブロック B、ブロック C があり、LRU に基づいて最も長期間使用されていないブロックとしてブロック C が計算された場合、ブロック C は削除されます。全体像を見ると、良くありません。ブロック C にはクラスター全体でコピーが 1 つしかないためです。それが排除された後、ブロック C にアクセスしたい人が下位にまだいる場合、彼らはリモート エンドからしかデータを取得することができず、パフォーマンスとコストの損失が発生します。私たちは世界的な排除戦略を立てることを提案します。この場合、ブロック C を削除するのではなく、コピー数が多い方を削除する必要があります。この例では、ブロック A は他のノードにまだ 2 つのコピーがあり、コストとパフォーマンスの点で優れているため、ブロック A を削除する必要があります。

上の図に示すように、私たちが行うことは、各ワーカーのレプリカ情報を維持することです。たとえば、ワーカーがコピーを追加したり、コピーを削除したりすると、最初にマスターに報告され、マスターはこの情報をハートビート戻り値として他の関連ワーカーに返します。他のワーカーは、グローバル コピー全体のリアルタイムの変更を知ることができます。同時にコピー情報も更新されます。したがって、内部ワーカーを削除する場合、各ワーカーが全世界に何個のコピーを持っているかを知ることができ、その後、いくつかの重みを設計できます。例えば、LRUは現在も使用されていますが、レプリカ数の重みを加えて、どのデータを削除して置き換えるかを総合的に検討します。予備テストの後、ビッグデータであろうと AI トレーニングであろうと、多くの分野で大きな改善がもたらされる可能性があります。つまり、1 台のマシン上の 1 人のワーカーのキャッシュ ヒットを最適化するだけではありません。私たちの目標は、クラスター全体のキャッシュ ヒット率を向上させることです。

最後に全文の要約を作成します。まず、AI トレーニング シナリオでは、均一なキャッシュ削除アルゴリズムが従来の LRU や LFU よりも優れています。次に、キャッシュとリモート ネットワーキングも、割り当てとスケジュール設定が必要なリソースです。第三に、キャッシュの最適化を実行するときは、1 つのジョブまたは 1 つのワーカーに限定せず、エンドツーエンドのグローバル パラメーター全体を制御して、クラスター全体の効率とパフォーマンスを向上させる必要があります。

さらに興味深い[イベント情報][技術記事][ビッグコーヒービュー]については、[Alluxio Think Tank]に注目してください

産業情報技術省: 未登録のアプリにネットワーク アクセス サービスを提供しない Go 1.21 が正式リリース Linus がコードを個人的にレビュー、Bcachefs ファイル システム ドライバーに関する「内紛」を鎮めることを期待 ByteDance が パブリック DNS サービスを開始 7-Zip 公式Web サイトは Baidu によって悪意のある Web サイトとして識別されました Google、AI コード エディターをリリース: Project IDX 清華レポート: Wenxin Yiyan が中国で確固たる地位を確立、ChatGPT Vim プロジェクトを超え、将来の 瞑想ソフトウェアが発売される予定、 ChatGPT は「中国初の Linux」によって設立されました「人」の1日あたりのコストは約70万米ドル、OpenAIは破産寸前になる可能性がある
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/5904778/blog/10096045