この記事はEnvision仮想マシン内部の仕組み、つまりEnvisionスクリプトを実行するソフトウェアに関する全4部作の第1部です。パート2パート3およびパート4もご覧ください。このシリーズではEnvisionコンパイラは扱っていないので、スクリプトが何らかの方法でEnvision仮想マシンの入力となるバイトコードに変換されたと仮定します.

A 供給チェーン最適化パイプラインは、データ取り込みや拡張、特徴抽出、確率的予測、制約下での最適な意思決定の生成、データエクスポート、分析、およびダッシュボード作成など、幅広いデータ処理ニーズに対応します。各企業のパイプラインは、入力、ルール、制約、出力がそれぞれ異なります。データ量は非常に多く、Lokadの経験では、最小規模のアカウントでも毎日ギガバイト単位のデータを処理しなければならず、大規模なアカウントでは1日あたり1テラバイトをはるかに超えます。また、最適化パイプラインは通常、社内の他のデータ処理システムからの毎日の入力を待つため、本日のデータに基づいて明日の意思決定を最適化するための計算時間はごくわずかです.

時系列を超えて

それは難しいことではありません。本当に。数時間で数テラバイトを処理するという性能目標は、熟練したソフトウェアエンジニアのチームなら十分に達成可能です.

Lokadの課題は、ソフトウェアエンジニアを使わずにそのようなパイプラインを構築することです。もちろん、Lokadにはソフトウェアエンジニアは存在しますが、彼らは個々の顧客向けではなく、会社全体のツールやインフラの開発に従事しています。その代わり、我々はサプライチェーンサイエンティストという、各顧客の特定の問題を深く理解し解決策を設計するサプライチェーンの専門家チームを抱えています。より従来型の企業構造であれば、彼らは顧客の声を聞き、ソフトウェアエンジニアに何を実装すべきかを詳細に伝えるプロダクトマネージャーに相当するでしょう。我々の開発哲学、そして独自のプログラミング言語であるEnvisionを作った理由は、サプライチェーンサイエンティスト自身が解決策を実装するほうが、他者に仕様を書かせるよりも速いという考えに基づいています.

スケールや性能を犠牲にすることなくこれを実現するために、Envisionはサプライチェーンサイエンティストの手間をかけずに、無料で提供されるべき3つの機能を備えていなければなりません[^1].

  • メモリ管理は自動でなければなりません。これは当然ガベージコレクターを含みますが、同時にEnvisionが大規模なデータセットを透過的にサポートすることも意味します。10ギガバイトの配列を作成するのは基本中の基本であり、それはまだ30億個の数値にも満たないのです! 単一マシンのメモリを超えるデータセットで作業できる能力が求められます。実際、EnvisionはNVMeドライブへの巧妙なスピリングにより、クラスター全体のメモリを超えるデータセットをサポートしています.

  • マルチコアおよびマルチマシンの並列処理も自動でなければなりません。あまりにも単純な並列処理は、人間の介入なしにクラスター上の可能な限り多くのコアに分散されるべきです。スクリプトは、クラスター内の単一マシンがクラッシュしても再実行する必要はなく、クラスターが単一マシンに縮小された場合でも完了できなければなりません。そしてもちろん、同一クラスター上で2つのEnvision実行が同時に動作できることも必要です.

  • Envisionは、動作するために必要なハードウェアが少なくて済むことが求められます。多くの性能問題は、高性能ハードウェアやサーバーライセンスに数百万ドルを費やすことで解決できますが、スクリプトの「実行」ボタンをクリックするだけで数百ドルのコストが発生する状況は避けたいのです.

汎用プログラミング言語はこれらの機能を提供しておらず、通常はそれらを実現するフレームワーク(Scala + Spark、Python + Daskなど)と組み合わせることになりますが、その場合ユーザーに露呈する厄介な点が多すぎます。この意味で、EnvisionはBigQuery上で動作するSQLに近いものとなっています.

環境

Envisionはローカルにインストールまたは実行することはできません。代わりに、すべてのユーザーはスクリプトを編集・実行するためのブラウザベースのIDEを提供するLokadのオンラインプラットフォームに接続します。データおよびダッシュボードもオンラインに保存され、ウェブインターフェース、SFTP、FTPSを通じてアクセスされます.

ユーザーがウェブインターフェースを介してスクリプトを実行すると、実行用にEnvisionクラスターへ派遣されるミッションが作成されます.

Envisionはバッチモードで動作します。すなわち、各実行は全ての入力データを読み取り、完全な出力を生成します。これは、非常にシンプルで少量のデータを処理するスクリプトでは5秒、大規模なデータ拡張スクリプトでは30~40分、さらに一部の機械学習タスクでは数時間かかることもあります.

リアルタイム処理(新たな入力を常時監視し、即座に対応する出力を生成する)やトランザクショナルアクセス(数行のデータを読み取り、数行を書き戻す)などの他の実行モードはサポートされていません。なぜなら、これらのモードを適切なパフォーマンスで実行するために必要な言語プリミティブや低レベルの実装の詳細が、バッチモード処理で関与するものと相容れないからです.

クラスター構造

2021年時点で、すべてのEnvisionは.NET 5上で動作しており、Microsoft Azureクラウド上のUbuntu 20.04仮想マシンでホストされています。クラスターは、2~6台のStandard_L32s_v2インスタンスで構成され、各インスタンスは32× AMD EPYC 7551コア、256GiBのメモリ、および合計7.68TBのストレージ容量を持つ4つのNVMeドライブを備えています。これらのマシンをワーカーと呼びます.

クラスターは、ワーカーとミッションとの間にM対Nの関連付けを持っており、1台のワーカーが複数のEnvisionスクリプトを同時に実行でき、もし1つのスクリプトが複数のワーカーに割り当てられた場合、より高速に完了するために協力します.

各クラスターには、2コアおよび8GiBのメモリを持つ、より小型のStandard_B2msインスタンスであるスケジューラーが存在します。スケジューラーは、外部アプリケーションが新規ミッションを送信し、完了したミッションの結果を収集するためのAPIエンドポイントを提供します。また、ミッションをクラスター内の1台以上のマシンに派遣する役割も担っています。負荷や各スクリプトが利用可能な並列性の度合いに応じて、スケジューラーはミッションに対してワーカーを追加または削除することができます.

システム全体は耐障害性を考慮して設計されています。一度ミッションがワーカーに割り当てられると、クラスター内の他のすべてのワーカーやスケジューラーがオフラインになった場合でも、生き残ったワーカーがミッションを完了することが可能です。したがって、ワーカー間の協力やスケジューラーによるミッションの再割り当ては_性能最適化_に過ぎず、ミッション完了に必須ではありません.

Blobストレージ

Lokadは顧客データにSQLデータベースを使用していません。ホスティングされたソリューションでは、大口顧客のデータセット(通常4TB~16TBに達する場合が多い)を簡単に保持することができず、自社サーバーの運用には他の領域に注力する必要があります.

一方、Envisionはバッチモードで動作するため、「行LからMの間で列Xを読み取る」というような複雑なクエリは不要です。一度入力データが読み込まれれば、ワーカーは必要に応じてデータをインデックス化し再処理できます.

このため、Azure Blob Storageを主要なストレージとして使用しています。これにより、ホスティングされたSQLデータベースのコストの1%未満で1ペタバイト以上のデータを保存でき、読み取りクエリのパフォーマンスは安定して30MB/sから60MB/sの範囲に収まります.

さらに、我々はブロブを不変(イミュータブル)に設定しています。つまり、新しいブロブの作成は可能ですが、既存のものを変更することはできません。これにより、スクリプト実行中に入力が変更されることなく、またスクリプトの出力も実行完了後に新たなブロブの識別子が返されるまで閲覧できなくなります.

正確に言えば、LokadはAzure Blob Storage上にコンテンツアドレス指定ストアを構築しました。これはオープンソースであり、NuGetパッケージLokad.ContentAddrおよびLokad.ContentAddr.Azureとして利用可能です。個々のファイルのハッシュ値を知ることで、Envisionは一部の入力が変更されていないと判断し、前回の実行でキャッシュされた計算済みの値を再利用することができます.

デプロイ

EnvisionはDockerなどのコンテナ化を利用していません。なぜなら、コンテナの利点が追加の複雑さを正当化しないためです.

第一に、高性能コンピューティングはワーカーの持つCPU、RAM、ストレージの隅々まで活用するため、同一マシン上で複数のアプリケーションを同時に動作させることはできません.

第二に、プラットフォームに依存せずにアプリケーションとそのすべての依存関係をパッケージ化するために、我々はdotnet publishで十分であると判断しています(実際、docker buildよりも速いです)。.NET 5では、Microsoftが卓越したクロスプラットフォームサポートを提供しており、Windowsマシンでのビルド成果物をそのままLinuxホストにコピーするだけで済みます.

最後に、新規インスタンスを迅速にゼロから作成することは、我々が積極的に避けている事項です。コスト削減のためにワーカーを停止することは可能ですが、新たなクラスターの作成や既存クラスターへのワーカー追加は_財務上_の判断となり、リソース使用量に基づいて顧客に請求していないため、追加コストを転嫁する方法がありません.

来週は、Envisionの実行モデルと、実行すべき作業がクラスター内でどのように表現されるかについて詳しく掘り下げます.

厚かましい宣伝ですが、ソフトウェアエンジニアを募集しています。リモートワークも可能です.