好奇心のためのレイ

ディーン-ワンプラー

フォローしている

2019年12月19日•10分読み取り

(リファイニング、二月8, 2020)

TL;DR Rayは、最小限の労力で計算クラスター間でPythonアプリケーションをスケーリングするためのシステ この記事では、Rayが解決する問題とその使用方法について説明します。

Rayプロジェクトローカル,
Rayプロジェクトは、https://ray.io

Ray(website,GitHub)は、Pythonアプリケーションを単一のマシンから大規模なクラスターにスケーリングするためのオープンソースのシステムです。 その設計は、多様な計算パターン、分散、進化する状態の管理、最小限のプログラミング労力でこれらすべてのニーズに対処したいという欲求など、いくつかのユニークな課題に直面している次世代のML/AIシステムのユニークなニーズによって推進されています。

一般的なML/AIシステムでは、データのクリーニングと準備、ハイパーパラメータチューニング、モデルトレーニングとサービング、およびその他の雑用をサポートするた ビッグデータワークロード用の元のMapReduceモデルは、データのクリーニング、準備、および分析ワークロードにも適していますが、機械学習ワークロードには、コンポーネント間の ハイパーパラメータチューニングとモデルトレーニングは非常に計算集約的であり、クラスターリソースを合理的な時間枠で完了する必要があります。 Rayは、最小限で直感的なAPIを使用して、これらの多様な要件を高性能に満たすことにより、最新のML/AIシステムとアプリケーションを構築するための基

第二の課題は、分散し、進化した状態です。 ML/AIの文脈では、分散状態には、ハイパーパラメータ、モデルパラメータ(たとえば、強化学習シナリオの場合は、訓練に使用されるシミュレーションの状態(または実 多くの場合、状態は特にトレーニング中に変更可能であるため、慎重で並行性に安全な更新が必要です。 分散コンピューティングを扱う一つの可能な方法は、一般的な”サーバーレス”システムを利用することですが、現在、分散された可変状態を管理するための機 開発者は、servelessシステムを使用する場合、データベース内のすべての状態を維持することに頼る必要がありますが、データベースはボトルネックと単一障害点

代わりに、Rayは一般的なアクターモデルを使用して、状態管理のための直感的なメカニズムを提供します。 Rayアクターは、ステートレスなRayタスクをステートフルに補完します。 この状態は、対応するPythonオブジェクト(つまり、Pythonクラスのインスタンス)への参照を通じて、他のRayアクタまたはタスクに透過的に到達できます。 Rayはアクタがクラスター内のどこにあるかを追跡するため、ユーザーコード内のそのような場所を明示的に把握して管理する必要がなくなります。 アクター内の状態の変更は、明示的な同時実行プリミティブを必要とせずに、スレッドセーフな方法で処理されます。 したがって、Rayはアプリケーションに対して直感的で分散した状態管理を提供します。 さらに、同じマシン上のアクタまたはタスク間で通信する場合、状態は共有メモリを介して透過的に管理され、アクタとタスク間のコピーシリアル化は

最後に、ほとんどのML/AIシステムはPythonベースであるため、開発者は最小限のコード変更でこれらのスケールアウト機能を追加する方法が必要です。 デコレータ@ray.remoteは、関数とクラスをクラスタ内でインスタンス化して実行できる論理単位としてマークします。 Rayは、状態のスレッドセーフな突然変異、状態の分布、および依存タスクの直感的なスケジューリングを透過的に処理します。

Rayの配布には、AIアプリケーションを対象としたいくつかの高性能ライブラリが含まれており、Rayの作成を推進する問題もありました。 それらには、強化学習のためのRLlibとハイパーパラメータチューニングのためのTuneが含まれています。 どちらもレイのユニークな機能を実証しています。 これらのライブラリや、Rayで記述されたその他のカスタムアプリケーションは、多くの実稼働環境ですでに使用されています。

Rayは、UC Berkeley RISELabで開始されたオープンソースプロジェクトです。 それは他の多くの組織からの主要な貢献のAnyscaleで今開発される。 Rayの商用ユーザーには、Ant Financial、JP Morgan、Intel、Microsoft、Ericsson、Skymind、Primerなどが含まれます。

Core Ray APIの例

注:次のコード例の完全なリストは、この記事の最後にあります。

Rayの動機と利点を理解したので、アプリケーションでRay APIをどのように使用するかを調べてみましょう。 次に、Rayが並列化と分散によってパフォーマンスをどのように向上させるかをより詳しく見ていきます。 Ray APIは、ユーザーが最小限のコード変更で、クラスター全体でもアプリケーションを拡張できるように慎重に設計されています。

クラスター内の機械学習モデルのトレーニングに使用されるキー値ストアであるパラメータサーバーの例を考えてみましょう。 値は、機械学習モデルのパラメータです(例:、ニューラルネットワーク)。 キーは、モデルパラメーターのインデックスを作成します。 パラメータサーバーに慣れていない場合は、情報やデータの要求を処理するために必要なスタンドアロンサービスを考えてください。

たとえば、映画推薦システムでは、ユーザーごとに一つのキーと映画ごとに一つのキーがある可能性があります。 各ユーザーとムービーには、対応するユーザー固有のパラメーターとムービー固有のパラメーターがあります。 言語モデリングアプリケーションでは、単語がキーであり、それらの埋め込みが値である可能性があります。

最も単純な形式では、パラメータサーバは単一のキーを持ち、すべてのパラメータを一度に取得および更新できるようにすることができます。

ここでは、パラメータの単一のNumPy配列のための、このような単純なパラメータサーバの例です。 これは、15行以下のコードでRayアクターとして実装されています:

ParameterServerアクタのインポートと定義

@ray.remoteデコレータはサービスを定義します。 これは通常のPythonクラスParameterServerを取り、リモートサービスとしてインスタンス化することを可能にします。 インスタンスは状態(変更可能な現在のパラメータ)を維持するため、ステートフルなサービスがあります。

この例では、パラメータの更新は、現在のパラメータベクトルに追加する必要がある勾配として提供されると仮定します。 (この勾配は、すべての配列要素または勾配の配列に追加される単一の数値にすることができます。)もちろん、より洗練されたデザインは可能ですが、Rayは同じ方法で使用されます。 簡単な練習として、これをkey-value(dictionary)実装に変更してみてください。

パラメータサーバは、通常、リモートプロセスまたはサービスとして存在します。 クライアントは、リモートプロシージャコールを介して対話します。 パラメーターサーバーをリモートアクタとしてインスタンス化するには、対話型のPythonプロンプトで次の手順を実行します。 (同じセッションでParameterServerクラスを既に定義していると仮定します)。 まず、Rayを起動する必要があります。 クラスターを使用する場合は、オプションのパラメーターをinit()メソッドに渡して、クラスターの場所を指定します:

Python対話型セッション: Start Ray

次に、10個のパラメータの配列のParameterServerインスタンスを作成します:

ParameterServerアクターインスタンスを構築する

ParameterServer(10)を呼び出してインスタンスを構築する代わりに、通常のPythonインスタンスの場合と同様に、remote()メソッドを使用します。@ray.remoteデコレータによってクラスに追加されました。 通常のコンストラクタに渡すのと同じ引数を渡します。 Actorオブジェクトが構築されることに注意してください。

同様に、アクターでメソッドを呼び出すには、元のメソッド名に追加されたremote()を使用し、元のメソッドに渡すのと同じ引数を渡します:

リモートメソッドを呼び出す

アクターメソッドの呼び出しは、先物を返します。 実際の値を取得するには、ブロッキングray.get(id)呼び出しを使用します:

rayで値を取得します。get(id)

予想通り、初期パラメータ値はすべてゼロです。 ray.get(id)が実際に行うことは、Rayが提供する分散状態ストアサービスから値を引き出すことです。 この値は、状態を更新したときにアクターによって分散状態ストアに書き込まれました。 値とクライアントの両方が同じマシン上にある場合、値は高速なパフォーマンスのために共有メモリから取得されます。 値とクライアントが異なるマシンに常駐している場合、値はそれを必要とするマシンに引き渡されます。

完全性のために、コードはray.put(id, value)を使用してこのストレージに明示的に値を書き込むこともできます。 いくつかの値が利用可能になったときに取得したい場合は、便利なray.wait(…)関数が利用できます。 詳細については、Ray APIを参照してください。

アクターモデルに続いて、クライアントがこれらのアクターメソッドを呼び出すと、呼び出しはクラスター内のどこにいてもアクターインスタンスにルーテ 同時呼び出しが発生する可能性があるため、Rayは各呼び出しがスレッドセーフな方法で処理されることを保証するため、明示的なスレッド同期コード しかし、これは、これらの呼び出しが処理されるときのグローバルな順序付けを課すものではありません。

注: Pythonの動的な性質のため、Rayでremote()なしでアクターメソッドを呼び出すことは可能でしたが、明示的なコード変更は、ローカルメソッド呼び出しからRPCのような呼び また、返されるオブジェクトはfutureとは異なり、値を抽出するためにブロッキング呼び出しray.get()を使用する必要があります。

ここで、勾配を継続的に計算し、モデルパラメータを更新するいくつかのワーカータスクを実行したいとします。 各ワーカーは、次の3つのことを実行するループで実行されます:

  1. 最新のパラメータを取得します。
  2. パラメータの更新を計算します。
  3. パラメータを更新します。

これらのワーカーはステートレスになるため、アクターの代わりにRayタスク(リモート関数)を使用します。 worker関数は、パラメーターサーバーアクターへのハンドルを引数として受け取り、ワーカータスクがパラメーターサーバー上のメソッドを呼び出すことができます:

パラメーターの更新を実行するリモートワーカーを定義します

次に、これらのワーカータスクの2つを次のように開始できます。 Rayタスク(関数)は、同じremote()呼び出しで開始されます:

2つのタスクを使用して、同時に

でパラメータの更新を計算すると、ドライバプロセスからパラメータを繰り返し取得し、ワーカーによって更新されているこ:

現在のパラメータ値に対してクエリを繰り返します

更新が停止すると、最終的な値は200になります。

Rayは、Pythonクラスを定義するのと同じくらい簡単にリモートサービスやアクタを起動できることに注意してください。 アクターへのハンドルを他のアクターやタスクに渡すことで、任意で直感的なメッセージングや通信パターンを可能にすることができます。 現在の選択肢ははるかに複雑です。 たとえば、このドキュメントのように、同等のランタイムサービスの作成とサービスハンドルの渡しがGRPCでどのように行われるかを考えてみます。

タスクとアクタの統一

タスクとアクタは同じRay APIを使用し、同じ方法で使用されていることがわかりました。 この並列タスクとアクタの統一には、Rayの使用を簡素化することと、合成を通じて強力なアプリケーションを構築することの両方に重要な利点があ比較すると、Apache HadoopやApache Sparkなどの一般的なデータ処理システムでは、ステートレスなタスク(副作用のない関数)が不変データで動作することができます。 この仮定は、システム全体の設計を簡素化し、アプリケーションが正確性について推論することを容易にします。

しかし、共有された可変状態は機械学習アプリケーションでは一般的です。 その状態は、ニューラルネットワークの重み、サードパーティのシミュレータの状態、または物理的な世界との相互作用の表現である可能性があります。 Rayのアクター抽象化は、スレッドセーフな方法で変更可能な状態を定義および管理する直感的な方法を提供します。

これを特に強力にするのは、Rayがアクター抽象化とタスク並列抽象化を統合する方法であり、両方のアプローチの利点を継承しています。 Rayは、基になる動的タスクグラフを使用して、アクタとステートレスタスクの両方を同じフレームワークに実装します。 結果として、これらの2つの抽象化は完全に相互運用可能です。 タスクとアクタは、他のタスクとアクタ内から作成できます。 どちらもfutureを返し、他のタスクやアクターメソッドに渡して、スケジューリングやデータの依存関係を自然な方法で導入することができます。 その結果、Rayアプリケーションは、タスクとアクタの両方の最高の機能を継承します。

以下に、Rayで内部的に使用されるコア概念をいくつか示します。

動的タスクグラフ:リモート関数またはアクターメソッドを呼び出すと、タスクが動的に成長するグラフに追加され、Rayはクラスター(または単一のマルチコアマシン)全体でスケジュールおよび実行されます。 タスクは、”ドライバ”アプリケーションまたは他のタスクによって作成することができます。

Data:RayはApache Arrow dataレイアウトを使用してデータを効率的にシリアル化します。 オブジェクトは、共有メモリを介して同じマシン上のワーカーとアクタの間で共有されるため、コピーや逆シリアル化の必要はありません。 この最適化は、良好なパフォーマンスを達成するために絶対に重要です。

Scheduling:Rayは分散スケジューリングアプローチを使用します。 各マシンには独自のスケジューラがあり、そのマシン上のワーカーとアクタを管理します。 タスクは、アプリケーションとワーカーによって、同じマシン上のスケジューラに送信されます。 そこから、それらを他のワーカーに再割り当てしたり、他のローカルスケジューラに渡すことができます。 これにより、Rayは集中スケジューラ、潜在的なボトルネック、単一障害点で達成できるものよりも大幅に高いタスクスループットを達成することができま これは、多くの機械学習アプリケーションに不可欠です。

結論

パラメータサーバーのようなシステムは、通常、配布、呼び出し、状態管理などを処理するための定型的なコード量ではなく、スタンドアロンシステムとして実装され、出荷されています。 Rayの抽象化と機能により、その定型文のほとんどを排除することが可能になることがわかりました。 それ故に、あらゆる特徴の強化は比較的容易であり、あなたの生産性は最大になる。

今日の本番環境で必要とされる一般的なサービスの多くは、このように、迅速かつ効率的に実装することができます。 例としては、ロギング、ストリーム処理、シミュレーション、モデル提供、グラフ処理、および他の多くが含まれます。

私はあなたが興味をそそるレイへのこの簡単な紹介を見つけたことを願っています。 それを試してみて、私はあなたが何を考えて知ってみましょうしてくださRayの詳細については、次のリンクを参照してください。

詳細については、

Rayの詳細については、次のリンクを参照してください:

  • Ray website
  • Ray GitHub page
  • Ray documentation:ランディングページ、インストール手順
  • Ray tutorials
  • Rayシステムを詳細に説明する研究論文
  • ディープラーニングのためのRay内部の柔軟なプリミティブを説明する研究論文
  • RayとApache Arrowによる高速シリアル化
  • RLlib:Rayによるスケーラブルな強化学習(およびこのRLlib研究論文)
  • Tune:Rayによる効率的なハイパーパラメータチューニング
  • Modin:rayによるパンダの高速化
  • Flow: トラフィック制御モデリングのための強化学習を使用した計算フレームワーク
  • Anyscale:Ray

の背後にある会社の質問は、Ray DiscourseまたはRay Slackワークスペースに

付録:コードの実行

完全なアプリケーションを実行するには、まずpip install rayでRayをインストールします(またはRayのインストール手順を参照してください)。 次に、Pythonで次のコードを実行します。 前に説明したようにパラメータサーバーを実装しますが、ワーカー内のパラメータのシャーディングを追加します。 また、この例のより広範なバージョンをJupyter notebook hereとして見つけることもできます。

この例では単純さに焦点を当てており、このコードを最適化するためにさらに多くのことを行うことができます。

コメントを残す

メールアドレスが公開されることはありません。