ノードが異なるレートの消費者と生産者であるリアルタイムネットワークをシミュレートしようとしています。このサンプルを Python ですばやく実装するにはどうすればよいでしょうか? ノードごとに簡単なプログラムを書くことを想像していましたが、それらを相互に接続する方法がわかりません。
8 に答える
少なくとも最初は従来のシミュレーション構造に固執する
演習として非同期システムを作成することが目標ですか? もしそうなら、マルチプロセスまたはネットワークシステムではないにしても、少なくともマルチスレッドを実装する必要があると思います。
しかし、それが本当にシミュレーションであり、分析結果が必要な場合、実際の分散モデルを実装することは、抽象的なシミュレーションよりもはるかに少ないデータを生成する可能性が高い、非常に複雑なアプローチになります。つまり、シミュレーション自体はそうではありません。通信する非同期アクターのネットワークでなければなりません。それは、問題を解決できないほど難しくするための良い方法です。
つまり、従来のシミュレーション アーキテクチャに固執するということです。
古典的な離散イベント シミュレーション
これが機能する方法は、保留中のイベントのソートされたコレクションを中心的なデータ構造として持つことです。イベントは時間の増加によって自然にソートされます。
プログラムにはメイン ループがあり、コレクションから次の (つまり、最も低い値の) イベントを取得し、シミュレーション クロックをこのイベントの時間まで進めてから、イベントに関連付けられたタスク固有の処理を呼び出します。
しかし、シミュレーターがジャンプしたばかりのタイム デルタで何かが発生するとしたらどうなるでしょうか? まあ、定義上、何もありませんでした。シミュレーションの個々の要素がその間隔で何かを発生させる必要がある場合、イベントを割り当てて (並べ替えられた) コレクションに挿入する必要がありました。
シミュレーション向けのパッケージやプログラムは数多くありますが、シミュレーションの根幹はそれほど難しくなく、好きな言語でゼロから作成することは完全に理にかなっています。
楽しむ!
プロセス間通信は、一般的に正しく行うのが難しいものです。離散イベント シミュレーターなど、別のアプローチがニーズを満たすかどうかを検討することをお勧めします。
DES では、実際に各ノードの作業を行うのではなく、各ノードが作業を完了するのにかかる時間をシミュレートするだけです。プライオリティ キューを使用して、着信および発信作業を追跡し、システムをインストルメント化して、グローバルおよび各ノードのキュー サイズを追跡できます。
達成しようとしていることについて詳細を提供していただければ、より具体的な推奨事項を提供できます。
編集: Python には、heapq
モジュールに組み込みの優先キューがあります。 http://docs.python.org/library/heapq.htmlを参照してください。
@DigitalRoss と dcrosta の離散偶数シミュレーションの提案が気に入っています。また、Python 標準ライブラリのschedモジュールが、そのようなシステムのコアで必要なものであることを指摘したいと思います (コアを再構築する必要はありません)。 heapq の上、またはそれ以外)。通常のandsched.scheduler
の代わりに、時間の経過をシミュレートする 2 つの callable をインスタンスに渡して、インスタンスを初期化するだけです。time.time
time.sleep
例えば:
class FakeTime(object):
def __init__(self, start=0.0):
self.now = start
def time(self):
return self.now
def sleep(self, delay):
self.now += delay
mytimer = FakeTime()
s = sched.scheduler(mytimer.time, mytimer.sleep)
スケジューラをインスタンス化するために使用します。
ネットワークを作成および操作するための Python ライブラリであるNetworkX を 調べてください。編集: NetworkX に近い/関連し、Los Alamos NL でホストされているのは、グラフを表示するためのユーティリティである PyGraphviz です。最初に間違ったリンクがあったことを指摘してくれた las3jrock に感謝します。
NetworkX をそのまま使用することも、このライブラリからインスピレーションを得ることもできます (このライブラリには、ネットワーク シミュレーションに必要と思われる「すべてのグラフ」が実際に含まれていることは気にしません)。操作により、ネットワークを表す (および成長 / 縮小 / 進化) ことができます。
前述のグラフ ライブラリに基づく単一の集中型オブジェクト/サービスでは、ネットワーク ノードの動作を表す 1 つ (または複数) のクラスを作成する必要があります。
次に、必要に応じて、ネットワークが比較的小さい場合は、ネットワーク ノードを効果的に「解き放ち」、スレッド内で実行できます。別の方法として (これは、シミュレーションの管理が容易な場合が多い)、ノードを反復処理し、適切な場合に「do_it」メソッドを呼び出す集中型のメソッドが存在する可能性があります。このような集中型コントローラーの「リフレッシュ レート」が十分に高い場合、ノード レベルのリアルタイム クロックを使用して、ノードの特定の動作をトリガーするタイミングを決定できます。このシミュレーションは、イベント ドリブンにすることも、単純にポーリングすることもできます (これも、クロックの基本時間単位に対してリフレッシュ期間が十分に短い場合です)。
ネットワークの集中化された「マップ」は、ネットワークノードが「ジョブ」を実行するために必要なさまざまなネットワーク関連のプリミティブを提供します(これが何であれ)。言い換えれば、ノードは「マップ」から、直接隣接するノードのリスト、完全なネットワークのディレクトリ、特定のノードへのルート (およびそのコスト) などを照会できます。
あるいは、ネットワークの構造は、インターネットのように、ネットワーク自体のノードに分散することもできます。この分散型アプローチにはいくつかの利点がありますが、ロジックとデータをノードに追加して、DNS とルーティングに相当するものを実装することを意味します。このアプローチには、ノード間のかなりの量のトラフィックが、ネットワークがエミュレートすることを意図した通信/交換のセマンティクスではなく、ネットワークのトポロジの発見と維持に関連している必要があるという欠点もあります。一言で言えば、このような分散型ネットワーク管理システムのプロトコルそのものを研究することを目的としたシミュレーションでない限り、この分散型アプローチを使用することはお勧めしません。
編集:
いくつかの返信で提案されているDESアプローチは、質問のシミュレーション部分に確実に対処しています。問題のネットワーク部分が重要な場合、強力なグラフ ライブラリに基づいて仮想ネットワークを実装することが、ソリューションの重要な部分になります。このようなアプローチは、ネットワーク トポロジに関連付けられたシステムのダイナミクスをより容易に明らかにします。
Stackless Pythonを使用し、タスクレットを作成し、それらをチャネルに接続するだけで、すべてが機能します。とてもシンプルです。
This is something Stackless does very well.
Also, you could use generators / co-routines.
Interesting links:
http://www.python.org/dev/peps/pep-0342/
New users can only post 1 hyper link... so here is the other one
'/'.join(['http:/', 'us.pycon.org', '2009', 'tutorials', 'schedule', '1PM6/'])
基本的なクライアント/サーバー プログラムの作成方法は次のとおりです: http://wdvl.internet.com/Authoring/python/client/watts06152009.html
データを別のデータに送信するには、これまでで最も単純な形式であるJSONをお勧めします。Python で実装する場合は、simplejson を確認してください: http://pypi.python.org/pypi/simplejson/
次の 2 つのことが思い浮かびます。
1- Twisted Python で 1 つまたは複数のデーモンを作成できます。(イベント駆動型の非同期システムであるため、twisted は少し圧倒される可能性があることに注意してください)。各デーモンは、ポートにバインドして、他のデーモンから利用できるようにすることができます。別の方法として、1 つのデーモン内ですべてを実行し、スクリプトを実行する各「プロセス」を異なる間隔で起動させ、バインドされたポートを介して相互に通信することもできます。
2-単一のイベント駆動型コアを使用できます-いくつかあります-そして、タスクごとに一連のプロセスまたはスレッドをフォークするだけです。