2

説明

私は現在、C# マルチエージェント シミュレーション用のアーキテクチャを設計しています。このアーキテクチャでは、エージェントのアクションは、センサーを読み取ったり、アクションに投票したり、他のモジュールにメッセージやクエリを送信したりする「頭脳」内の多くのモジュールによって駆動されます (これらはすべて、メッセージの交換)。もちろん、モジュールは状態を持つことができます。

モジュールは並行して実行されます。メッセージとクエリを消費し、何らかの計算を実行する update メソッドがあります。update メソッドは反復子を返し、その本体に複数の yield があるため、モジュールを協調的にスケジュールできます。エージェントごとに数百から数千のモジュールがあると予想されるため、モジュールごとに単一のスレッドを使用しません。これにより、スレッドのオーバーヘッドによって膨大な量の RAM が占有されることになります。

これらのモジュールをランタイム プラグインのように動作させて、シミュレーションの実行中に新しいモジュール クラスを追加し、シミュレーション プロセスを停止することなく既存のクラスを書き換え/デバッグし、それらのクラスを使用してモジュールを追加および削除できるようにしたいと考えています。エージェントの頭脳、またはメソッドの新しい実装により、既存のモジュールに動作を変更させるだけです。

可能な解決策

私はここ数日でいくつかの可能な解決策を考え出しましたが、どれもがっかりしました:

  1. モジュールを DLL にコンパイルし、それぞれを別のAppDomainにロードしてから、AppDomain.CreateInstanceFromAndUnwrap() を使用してモジュールをインスタンス化し、それをいくつかの IModule インターフェイスにキャストして、シミュレーションとモジュールの間で共有 (および各モジュール クラスによって実装) します。 . インターフェイスは、SendMessage、Update、およびすべてのモジュールに共通の他のいくつかのメンバーのみを公開します。

    • このソリューションの問題は、AppDomain 間の呼び出しが (同じ AppDomain 内の) 直接呼び出しよりもはるかに遅いことです。
    • また、AppDomains のオーバーヘッドはわかりませんが、無料ではないので、何千もあると問題になる可能性があります。
  2. アセンブリのロード/アンロードがないように、モジュールにはスクリプト言語を使用し、基になるエンジンには C# を使用します。代わりに、各モジュールのスクリプト言語の実行コンテキストをホストします。

    • 私の主な懸念は、大きなスクリプト言語 (「python、lua、ruby、js は大きく、Autoit と Euphoria はそうではない」など) を知らないことです。モジュール実行の協調スケジューリングを実行するために必要です)。
    • これに関するもう 1 つの懸念は、モジュールごとにランタイム コンテキストを使用する必要があり、その結果、膨大なオーバーヘッドが発生することです。
    • 最後に、スクリプト言語はおそらく C# よりも遅く、パフォーマンスが低下すると思います。
  3. アセンブリのアンロードを避け、代わりに何らかの方法で名前を変更/バージョン付けして、さまざまなバージョンを多数持つことができるようにし、タイプごとに最新のものを使用します。

    • これが可能かどうかさえわかりません(不愉快な型と名前空間のため)
    • たとえ可能であったとしても、それは非常にメモリ効率が悪いでしょう。
  4. 透過的にシミュレーションを再開します。つまり、シミュレーション (およびブレイン/モジュールのスケジューラーの実行) を一時停止し、すべて (すべてのモジュールを含む) をシリアル化し、シミュレーションを終了し、コードを再コンパイルし、シミュレーションを再度開始し、すべてを逆シリアル化し、キャッチします。クラスに変更を加えて実行を再開したために発生した例外。

    • これは大変な作業なので、最後の手段と考えています。
    • また、このプロセス全体は、モジュールの数とそのサイズによっては、ある時点で非常に遅くなり、実用的ではなくなります

この最後の問題 (ソリューション 4 のプロセス全体が遅くなる) を解決するには、ソリューション 3 と 4 を混ぜ合わせ、多数のアセンブリを何らかの形式のバージョン管理で読み込み、時々再起動して混乱を解消します。それでも、モジュール クラスに小さな変更を加えたからといって、シミュレーション全体を中断しないものを好むでしょう。

実際の質問

だからここに私の質問があります:他の解決策はありますか?私が見つけた問題の回避策を見逃していませんか? たとえば、私のニーズを満たす .NET 用のスクリプト言語はありますか (解決策 #2)? 私が漠然と説明した方法でバージョン管理は可能ですか (解決策 #3)?

または、もっと簡単に言うと、.NET はこのプロジェクトのプラットフォームとして適切ではないのでしょうか? (C# がメインの言語なので、このまま使い続けたいと思っていますが、必要に応じて Python などでこれを行うことも考えられます)

4

2 に答える 2

0

私は、エージェント モジュールをプラグインとして扱う、非常によく似た方法で動作するシミュレーション システムで作業しています。

関連するものをロードするすべてのドメインを処理し、ダミードメインでプラグインの有効性をチェックしてからエンジンドメインでホットロードするプラグインマネージャーを作成しました。

AppDomain を使用すると、完全に制御でき、プラグイン マネージャーのタスクを並行して実行することで処理時間を短縮できます。

AppDomains は無料ではありませんが、2 つ (検証ドメインと実行ドメインをさらに分離する必要がある場合は 3 つ) だけで処理できます。

プラグイン ファイルが検証されると、いつでもメイン プロセスでロードできます。任意のドメインのプローブ パス (または設定されている場合は動的パス) にシャドウ コピーを作成し、元のファイルの代わりにそれをターゲットにすると、バージョン管理と更新を確認するのに役立ちます。 .

ドメインを検証に使用し、別のドメインを実行に使用するには、更新中に以前のバージョンのインスタンスを処理するスワップ コンテキストが必要になる場合があります。

新しいプラグインと新しいバージョンをチェックし、プラグイン モジュールの使用をブロックし、ファイルをスワップし、リロードし、ブロックを解除し、必要に応じて以前のバージョンから新しいバージョンを再インスタンス化するための定期的なタスクを維持します。

于 2016-12-11T16:33:24.943 に答える