0

他の既知の/信頼できるノードからの受信データを同時に処理する小さな p2p アプリケーションを作成したいと思います (ほとんどの場合、SQLite データベースに格納されます)。これらのノードを認識するために、接続時に各ノードが自己紹介し、アプリケーションはこのノードを直接または別のノードを介して間接的に認識しているかどうかを確認する必要があります。したがって、明らかに処理時間が必要で、別のプロセス (または複数のワーカー プロセス) にアウトソーシングしたいグラフ検索を行う必要があります。以下の 2 番目の質問を参照してください)。また、場合によっては、グラフを調整したり、新しいエッジや頂点を追加したりする必要があります。

非同期 I/O 経由で着信接続を受け入れて処理する4 つのワーカー プロセスがあるとします。グラフにアクセス (読み取り/変更) するための最良の方法は何ですか? どうにかして検索結果を返す必要があるため、単一のキューでは明らかに読み取りアクセスのトリックは実行されません。

したがって、それを行う 1 つの方法は、グラフ検索プロセスによって満たされ、イベント ループに追加できる別のキューです。イベント ループは、結果をハンドラーに渡すことができます。ただし、このイベント/コールバックベースのアプローチでは、対応するソケットを常にコールバックに渡す必要があり、したがってキューにも渡す必要があります。これは、ソケットがピクル可能ではないため厄介です。(コールバックがスパゲッティ コードにつながるという事実は言うまでもありません。)

頭に浮かんだもう 1 つのアイデアは、着信接続ごとにグラフ プロセスへのパイプを作成し、グラフ側で非同期 I/O も行うことです。ただし、コールバックを回避するために、正しく理解していれば、非同期 I/O ライブラリを使用する必要がありますyield from(つまり、 tulip / PEP 3156 )。他のオプションはありますか?

グラフ側の非同期 I/O について: これは確かに、多くの着信要求を一度に処理するための最良の方法ですが、グラフ ルックアップの実行は CPU を集中的に使用するタスクであるため、複数のワーカー スレッドまたはプロセスを使用することで利益が得られる可能性があります。問題は次のとおりです。複数のスレッドが共有データを許可しますが、Python の GIL はパフォーマンスの利点をいくらか無効にします。一方、複数のプロセスにはこの問題はありませんが、それらの間でデータを共有および同期するにはどうすればよいですか? (私にとって、グラフを分割することはまったく不可能に思えます。) この問題をうまく解決する方法はありますか? また、非同期 I/O とマルチスレッド / マルチプロセッシングを混在させることは、パフォーマンスの観点から意味がありますか?

4

1 に答える 1

1

最後の質問への回答: そうです! しかし、私見ですが、問題は次のとおりです。イベントとスレッドを混在させるのは理にかなっていますか? ハイブリッド同時実行モデルに関するこの記事を確認できます: http://bibliotecadigital.sbc.org.br/download.php?paper=3027

ヒント: チューリップ モデルのように、1 つのプロセスと 1 つのイベント ループから始めます。tulip を使用して、コールバックをまったく使用せずにイベント + 非同期 I/O (およびスレッドまたはその他のプロセス) を実行する方法を説明しようと思います。

のようなものがaccept = yield from check_incoming()あり、これはチューリップ コルーチン (check_incoming) である必要があり、この関数内loop.run_in_executor()で、スレッド/プロセス プールでグラフ検索を実行するために使用できます (これについては後で詳しく説明します)。この関数run_in_executor()は Future を返しますyield from tasks.wait([future_returned_by_run_in_executor], loop=self)。次のステップは、最後にorresult = future_returned_by_run_in_executor.result()を返すことです。TrueFalse

プロセス プールでは、選択可能なオブジェクトのみを実行して返すことができる必要があります。この要件は問題ではありませんが、グラフ操作が関数内に自己完結している必要があり、何らかの形でグラフ インスタンスを取得する必要があることは暗示的です。「acquiring-gil-conflicts」につながる可能性のある CPU バインド タスクについて言及したため、スレッド プールには GIL 問題がありますが、これは新しい Python 3.x GIL で改善されました。どちらのソリューションにも制限があります。

したがって、プールの代わりに、すべてのグラフ作業を管理し、両方のプロセスをたとえば UNIX ドメイン ソケットに接続するためだけに、独自のイベント ループを持つ別の単一のプロセスを持つことができます。

この 2 番目のプロセスは、最初のプロセスと同様に、着信接続も受け入れる必要があり (ただし、現在は既知のソースからのものです)、前述のようにスレッド プールを使用できますが、最初のイベント ループ プロセスとは「競合」しません。 (外部クライアントを処理するもの)、2 番目のイベント ループのみ。同じグラフ インスタンスを共有するスレッドには、ロック/ロック解除が必要です。

それが役に立ったことを願っています!

于 2013-09-28T03:40:12.603 に答える