2017-12-03 22 views
1

私は、ソケットからデータを取得して処理するPython C-エクステンションを持っています。処理中にGILを解放します。現在、私は2つのPythonスレッドを使用しています。その2つのCPUコアに90%の負荷がかかり、結果的にGILを解放するためにうまく絡み合っています。Asyncio from Python C-エクステンション

私はPython 3 asyncioでどのように同じことを達成できますか? 私は正しいPython-C-APIコマンドを見つけられず、イベントループに行って別のことをすることができます。

または、私の拡張機能がGILをリリースした場合、これは自動的にイベントループで利用可能な次のアイテムの実行をブロックしないことを意味しますか?例えば。私のCエクステンションが最初のソケットのデータを処理している間に次のソケットが読み込まれますか?これは私がどこにも見つけることができません。 私がこのように理解していることから、私はいくつかのソケットからデータを取得し、より多くのCPUコアを動作させることができました。

+0

これは非常に良い質問ではありません。あなたはあなたのエクステンションがイベントループとどのように対話しているかを見せておく必要があります。あなたがそれを説明したように、あなたの拡張機能がイベントループと全くやり取りする必要はないとは思われません。 –

+0

あなたがあなたのエクステンションとイベントループとしたいと思っているインタラクションを記述する擬似コードを記述できるなら、それを行う方法を記述するのはおそらく可能でしょう。 –

+0

@SamHartmanそれもそうかもしれません。私の質問はほとんどが:私の拡張機能がGILをリリースした場合、これは自動的にeventloopで利用可能な次の項目の実行をブロックしないことを意味しますか? など。私のCエクステンションが最初のソケットのデータを処理している間に次のソケットが読み込まれますか?これは私がどこにも見つけることができません。 – Safihre

答えて

2

イベントループ内から拡張機能が呼び出された場合、GILをリリースしてもイベントループは継続しません。

async def process(): 
    call_your_extension() 

asyncio.get_event_loop.create_task(process()) 

は、イベントループが継続することはありません、あなたの拡張機能でGILを解放:ある

は、私のような何かを言います。あなたのルーチンは同期しています。

代わりに、あなたが戻るか、またはいくつかの種類のawaitableを作成し、このモデルでは

async def process() 
    await call_your_extension() 

を行うことができ、あなたの拡張機能は、おそらく__await__メソッドを持つクラスになります。最終的には、asyncio.futures.Futureを生成する必要があります。イベントループは完了したコールバックをその未来に付け加え、完了したコールバックが呼び出されるとprocessが再開することができます。 これはおそらく、複数のコアを使用したいものには適していないでしょう。イベントループは1つのスレッドでのみ実行されます。

concurrent.futuresを使用して、スレッドを越えて実行できる未来を生成することで、いくつかの利点を得ることができます。 asyncio.ensure_futureを使用してasyncio Futureに変換することができます。 しかし、これはすべて、イベントループがあなたの拡張に何らかの形で利益をもたらすと想定しています。 これは、ソケットからの読み取り値を拡張機能からイベントループコードに移動できる場合にのみ当てはまります。 そうしないと、現在のデザインがおそらく理想的です。 イベントループモデルと相互運用する必要がある場合は、asyncio.get_event_loop().run_in_executor

関連する問題