ホームページ > 記事 > テクノロジー周辺機器 > WeChat NLP アルゴリズム マイクロサービス ガバナンス
Musk は Twitter を買収しましたが、そのテクノロジーに不満を抱いていました。 RPC が 1000 を超えるため、ホームページが遅すぎると考えてください。マスク氏が述べた理由が正しいかどうかについてはコメントしませんが、インターネット上でユーザーに提供される完全なサービスの背後に多数のマイクロサービス呼び出しがあることがわかります。
# WeChat の読書推奨を例に挙げると、それは 2 つの段階に分かれています: 想起と並べ替え。
リクエストが到着すると、ユーザー特性マイクロサービスと特性から特性が取得されます。これらを組み合わせて機能スクリーニングを実行し、リコール関連のマイクロサービスを呼び出します。マルチチャネルのリコールがあり、同時に実行される同様のリコール プロセスが多数あるため、このプロセスにも N を掛ける必要があります。 。次は並べ替えステージで、複数の機能マイクロサービスから関連する機能を取得し、それらを結合した後に並べ替えモデル サービスを複数回呼び出します。最終結果を取得した後、一方では最終結果が呼び出し元に返され、他方ではプロセスのログの一部がアーカイブのためにログ システムに送信されます。
読書推奨事項は、WeChat 読書アプリ全体のごく一部にすぎません。比較的小規模なサービスであっても、多数のマイクロサービスがあることがわかります。その後ろに転送します。詳しく見てみると、WeChat Reading システム全体で膨大な数のマイクロサービス呼び出しが行われることが予想されます。
#多数のマイクロサービスはどのような問題を引き起こすのでしょうか?
#日々の業務をまとめると、主に上記 3 つの側面に課題があります。 :① 管理:
主に、多数のアルゴリズムを効率的に管理、開発、展開する方法に焦点を当てます。マイクロサービス。
② パフォーマンス:マイクロサービス、特にアルゴリズム マイクロサービスのパフォーマンスの向上を試みます。
③ スケジューリング: 複数の同様のアルゴリズム マイクロサービス間で効率的かつ合理的な負荷分散を実現する方法。
2. マイクロサービスが直面する管理問題最初のポイントは、アルゴリズムのマイクロサービスを開発するというアルゴリズムの学生へのプレッシャーを軽減するために、自動パッケージングとデプロイのパイプラインを提供するということです。現在、アルゴリズムの学生はあなただけです。 Python 関数を記述する必要がある場合、パイプラインは事前に作成された一連のマイクロサービス テンプレートを自動的に取得し、アルゴリズムの学生が開発した関数を入力して、マイクロサービスを迅速に構築します。
2. キャパシティの拡張と縮小: タスクのバックログを認識した自動拡張と縮小2 番目のポイントは、マイクロサービスについて 自動拡張と縮小のために、タスクバックログを認識したソリューションを採用しています。特定のタイプのタスクのバックログまたはアイドル状態の程度をアクティブに検出します。バックログが特定のしきい値を超えると、拡張操作が自動的にトリガーされます。アイドル状態が特定のしきい値に達すると、数の削減もトリガーされます。マイクロサービスプロセスの。 3 番目のポイントは、大規模なサービスを配置する方法です。多数のマイクロサービスがまとめて編成され、完全な上位層サービスが構築されます。 私たちの上位層サービスは DAG で表されます。DAG の各ノードはマイクロサービスへの呼び出しを表し、各エッジはサービス間のデータ転送を表します。 DAG の場合、DAG をより適切に記述および構造化するために、DSL (ドメイン固有言語) も特別に開発されました。また、DSL を中心とした一連の Web ベースのツールを開発しました。これにより、ブラウザ内で直接上位層サービスを視覚的に構築、ストレス テスト、デプロイできるようになります。 ##4 番目のポイントパフォーマンス監視、いつ上位層のサービスに問題があるため、問題を特定する必要があるため、独自の Trace システムを構築しました。外部リクエストごとに完全な追跡セットがあり、各マイクロサービスでのリクエストの消費時間をチェックして、システムのパフォーマンスのボトルネックを発見できます。 一般的に、アルゴリズムのパフォーマンス時間はディープ ラーニングに関するものです。アルゴリズム マイクロサービスのパフォーマンスの最適化の焦点の大部分は、深層学習モデルの推論パフォーマンスの最適化です。専用の推論フレームワークを選択するか、深層学習コンパイラー、カーネル最適化などを試すことができます。これらのソリューションについては、完全に必要なものではないと考えています。多くの場合、Python スクリプトを直接使用してオンラインに接続しますが、それでも C と同等のパフォーマンスを達成できます。 #これが完全に必要ではない理由は、これらのソリューションは実際により優れたパフォーマンスをもたらす可能性がありますが、優れたパフォーマンスだけがサービスの要件ではないからです。人材とリソースの観点から説明される、よく知られた 80/20 ルールがあります。つまり、20% の人材が 80% のリソースを生み出すことになります。言い換えれば、20% の人材が貢献の 80% を提供することになります。 。これはマイクロサービスにも当てはまります。 マイクロサービスは 2 つのカテゴリに分類できます。まず、成熟した安定したサービスは数が多くなく、20% しか占有しない可能性がありますが、トラフィックの 80% を負担します。もう 1 つのカテゴリは、実験的なサービス、またはまだ開発中および反復中のサービスです。これらは 80% を占め、数は多いですが、トラフィックの 20% しか占めていません。重要な点は、変更や反復が頻繁に行われることです。迅速な開発と立ち上げに対する強い要求もあるでしょう。 Infer フレームワークやカーネル最適化など、前述の手法では、必然的に追加の開発コストが必要になります。成熟した安定したサービスは、変更が比較的少なく、1 回の最適化で長期間使用できるため、このタイプの方法に非常に適しています。一方で、これらのサービスは大量のトラフィックを負担し、わずかなパフォーマンスの向上が大きな影響を与える可能性があるため、コストを投資する価値があります。 しかし、実験的サービスは頻繁に更新され、新しいモデルごとに新たな最適化を行うことはできないため、これらの方法は実験的サービスにはあまり適していません。実験的なサービスとして、GPU ハイブリッド展開シナリオ用に自社開発の Python インタープリター PyInter を開発しました。コードを変更せずに Python スクリプトを使用して直接オンラインに接続することが可能であり、同時にパフォーマンスは C に近いか、C を超える可能性があります。 3. マイクロサービス組織: Turing の完全な DAG/DSL/自動ストレス テスト/自動デプロイメント
#4. パフォーマンス監視: トレース システム
上の図から、PyInter には多数のモデルのコピーがあることがわかります。マルチプロセスや ONNXRuntime と比較すると、メモリ使用量は 80% 近く削減されており、モデルのコピー数に関係なく、PyInter のビデオ メモリ使用量は変わらないことに注意してください。
# 先ほどのより基本的な質問に戻りましょう: Python は本当に遅いのですか?
はい、Python は非常に遅いですが、実際の計算は Python で行われるのではなく、専用の計算ライブラリである MKL または cuBLAS を呼び出すことによって行われるため、Python は科学技術計算を実行する場合には遅くなりません。 #では、Python の主なパフォーマンスのボトルネックはどこにあるのでしょうか?主に、マルチスレッドでの GIL (グローバル インタープリタ ロック) が原因で、マルチスレッドでは 1 つのスレッドだけが同時に動作します。この形式のマルチスレッドは、IO 集約型のタスクには役立つかもしれませんが、計算集約型のモデルのデプロイメントには意味がありません。
#複数のプロセスに切り替えることで問題を解決できますか?
#実際、マルチプロセスは確かに GIL の問題を解決できますが、また、他の新しい疑問も生まれます。まず、CUDA コンテキスト/モデルを複数のプロセス間で共有するのは難しく、ビデオ メモリを大量に浪費するため、1 つのグラフィックス カードに複数のモデルを展開することはできません。 2 つ目は GPU の問題で、GPU は同時に 1 つのプロセスのタスクしか実行できず、複数のプロセス間で GPU を頻繁に切り替えることにも時間がかかります。
#Python シナリオの場合、理想的なモードは次のとおりです。
#マルチスレッドのデプロイメントと GIL の影響の除去を通じて、これは PyInter の主な設計アイデアでもあり、複数のモデルのコピーを複数のスレッドに配置して実行します。また、複数のタスクの GIL が相互に干渉しないように、Python タスクごとに個別の分離された Python インタープリターを作成します。これは、マルチプロセスとマルチスレッドの利点を組み合わせたもので、GIL は互いに独立している一方で、本質的には単一プロセス マルチスレッド モードであるため、ビデオ メモリ オブジェクトを共有できます。また、GPU プロセスの切り替えオーバーヘッドもありません。
PyInter の実装の鍵は、プロセス内の動的ライブラリの分離です。インタプリタの分離は、本質的に動的ライブラリの分離です。ここでは、独自に開発した動的ライブラリ ローダー。dlopen に似ていますが、「分離」と「共有」という 2 つの動的ライブラリ ロード方法をサポートします。
「分離」モードで動的ライブラリをロードすると、動的ライブラリは異なる仮想スペースにロードされます。仮想空間はお互いを見ることができません。ダイナミック ライブラリが「共有」モードでロードされる場合、ダイナミック ライブラリは、各仮想空間内を含むプロセス内のどこでも表示および使用できます。Python インタプリタ関連のライブラリを「分離」モードでロードし、次に cuda 関連のライブラリを「共有」モードでロードすることで、分離された解釈プロセッサを実現します。ビデオメモリリソースを共有しながら。
4. マイクロサービスが直面するスケジュールの問題
#動的負荷分散が重要なのはなぜですか?理由は次のとおりです:
(1) マシンのハードウェアの違い (CPU / GPU);
## (2) リクエストの長さの違い (翻訳された 2 ワード / 翻訳された 200 ワード);
(3) ランダムな負荷分散、ロングテール 効果は次のとおりです。明らか: #########
① P99/P50 の差は 10 倍に達する可能性があります;
② P999/P50 の差は 20 倍に達する可能性があります。
# (4) マイクロサービスの場合、ロングテールが全体の速度を決定する鍵となります。
#リクエストの処理にかかる時間は大きく異なり、コンピューティング能力、リクエストの長さなどの違いがすべて、かかる時間に影響します。マイクロサービスの数が増加すると、ロングテールに達するマイクロサービスが常に存在し、システム全体の応答時間に影響を与えます。
#動的負荷分散を完璧にするのがこれほど難しいのはなぜですか?
#オプション 1: すべてのマシンでベンチマークを実行します。
#このソリューションは「動的」ではないため、リクエストの長さの違いに対処できません。また、パフォーマンスを反映できる完璧なベンチマークはなく、マシンが異なれば、モデルが異なれば反応も異なります。
#オプション 2: 各マシンのステータスをリアルタイムで取得し、負荷が最も軽いマシンにタスクを送信します。
このソリューションは比較的直感的ですが、問題は、分散システムには実際の「リアルタイム」がなく、情報が 1 台のマシンから別のマシンに渡されることです。必ず時間がかかり、その間にマシンのステータスが変化する可能性があります。たとえば、ある瞬間に、特定のワーカー マシンが最もアイドル状態になり、タスクの分散を担当する複数のマスター マシンがすべてそれを感知し、すべてのマシンがこの最もアイドルなワーカーにタスクを割り当て、この最もアイドルなワーカーが即座に「This is」になります。負荷分散における有名な潮汐効果。
#オプション 3: グローバルに一意のタスク キューを維持するタスク分散を担当するすべてのマスターがタスクをキューに送信し、すべてのワーカーがキューからタスクを取得します。 。
#このソリューションでは、タスク キュー自体が単一点のボトルネックになる可能性があり、水平方向の拡張が困難になります。
動的負荷分散を完璧にすることが難しい根本的な理由は、情報の送信に時間がかかるためです。この状態は過ぎている必要があります。皆さんにお勧めする YouTube のビデオ「ロード バランシングは不可能です」 https://www.youtube.com/watch?v=kpvbOzHUakA があります。
動的負荷分散アルゴリズムに関しては、Power of 2 Choices アルゴリズムにより 2 つのワーカーがランダムに選択され、よりアイドル状態のワーカーにタスクが割り当てられます。このアルゴリズムは、現在使用している動的等化アルゴリズムの基礎です。ただし、2 のべき乗アルゴリズムには 2 つの大きな問題があります: まず、各タスクが割り当てられる前に、ワーカーのアイドル ステータスをクエリする必要があり、これにより RTT が追加されます。さらに、ランダムに選択された 2 つのタスクが割り当てられる可能性があります。労働者はたまたまとても忙しいです。これらの問題を解決するために、私たちは改善を行いました。
改良されたアルゴリズム は Joint-Idle-Queue です。
マスター マシンに Idle-Queue と Amnesia の 2 つの部分を追加しました。 Idle-Queue は、現在アイドル状態のワーカーを記録するために使用されます。 Amnesia は、最近どのワーカーが自分自身にハートビート パケットを送信したかを記録します。ワーカーが長期間ハートビート パケットを送信しなかった場合、Amnesia はそれを徐々に忘れていきます。各ワーカーは、アイドル状態であるかどうかを定期的に報告し、アイドル状態のワーカーは、そのアイドル状態を報告するマスターを選択し、処理できる数を報告します。また、ワーカーはマスターを選択するときに 2 の累乗アルゴリズムを使用し、他のマスターについてはハートビート パケットを報告します。
新しいタスクが到着すると、マスターはアイドル キューからランダムに 2 つを選択し、履歴レイテンシーが低い方を選択します。 Idle-Queue が空の場合、Amnesia が表示されます。 Amnesia からランダムに 2 つを選択し、履歴レイテンシーが低い方を選択します。
実際の効果としては、このアルゴリズムを使用すると、P99/P50 を 1.5 倍に圧縮でき、これはランダム アルゴリズムよりも 10 倍優れています。
モデルのサービス化の実践において、私たちは 3 つの課題に遭遇しました。
1 つ目は、多数のマイクロサービスを管理する方法と、開発、オンライン、デプロイのプロセスを最適化する方法です。私たちのソリューションは、可能な限り自動化し、反復的なプロセスを抽出して自動パイプラインにし、手順。
2 番目の側面は、モデルのパフォーマンスの最適化です。深層学習モデルのマイクロサービスをより効率的に実行する方法です。私たちの解決策は、モデルの実際のニーズから始めて、比較的安定していてトラフィックが大きいサービスをカスタマイズすることです。最適化、PyInter は実験的なサービスに使用され、Python スクリプトはサービスを直接起動するために使用されます。これにより、C のパフォーマンスも達成できます。
3 番目は、タスク スケジューリングの問題です。動的負荷分散を実現する方法です。私たちの解決策は、2 の累乗に基づいた JIQ アルゴリズム を開発することです。これは非常に大きな問題です。時間のかかるサービスのロングテール問題を軽減します。
以上がWeChat NLP アルゴリズム マイクロサービス ガバナンスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。