2016-11-20 12 views
0

私はかなりasyncioに新しく、次のシナリオを構築する方法についていくつかのアドバイスが必要です。私はコールバックを受け入れるCython拡張を持っています。前者は、新しいイベントが到着するたびに実行されます。しかし、それらのイベントを収集する機構を開始することは、ブロック動作であり、すなわち、主スレッドをブロックする。 また、Cython拡張はasyncio.Queueを受け入れ、コールバックからput_nowaitメソッドを呼び出します。これで、イベントを処理するキューのコンシューマを設定します。これは、シナリオの背後にある可能擬似コードのようになります。私は例を実行するとasyncioのトラブルとアドバイス

aioq = asyncio.Queue(1000)  
cext = CythonExtension(aioq) 

def c(aioq): 
    while not aioq.empty(): 
     e = yield from aioq.get() 
loop.create_task(c(aioq)) 

# i'm not sure how to run the event loop 
# and keep on initializing the cython extension 
# because this call also blocks... 
#loop.run_forever() 

# so i tried this. 

loop.run_in_executor(None, cext.start) <- this is a blocking operation 
# start the event loop 
loop.run_forever() 

asyncioキューがイベントで満たされているが、cタスクが実行されることはありません - 私は、キューからすべてのイベントを取得することはできませんよ。これに対処する方法に関するフィードバックや指摘を感謝します。

答えて

1

通常のPythonコードでは、特定のバイトコード操作が実行された後に別のスレッドが回転できるようになります。たとえば、メカニズムの改善について説明するが、メカニズムについても説明しているthis set of slidesを参照してください。

Cythonはバイトコードを実行しないので、このスワッピングの仕組みを決して引き起こさないので、Cythonスレッドは無限にブロックされます。それ丸い簡単な方法は、cext.startであなたのメインCythonループに以下の行を追加することである(それは、定期的に実行):

with nogil: 
    pass 

このリリースでは、その後すぐに可能にグローバルインタープリタロック(GIL)を、再利用しようとします実行する他のスレッド(別のスレッドが実行してからCythonが待機する必要がある場合)

さらに良いオプションは、GIL(主にPythonデータ型ではなくCデータ型を使用するビット)を必要としないCythonコードのビットを識別し、with nogil:ブロックにラップすることです。これにより、あなたのCythonコードは、別のスレッドが実行されている間に役に立つ何かを続けることができます。

+0

私の質問には答えません。しかし、それはGILの限界を克服するためにコードをリファクタリングする動機となっています。私は非常に高いパフォーマンスの向上を実験しています。 – Nedo

+0

まあ、何とか助けてくれてうれしいですね。私は本当にそれを助けるために十分に「asyncio」を理解していないのではないかと思います(この答えはCythonで時折起こる問題なので、少し推測でした)。 'CythonExtension'の簡略化されたサンプルコードを表示した場合、誰かがその質問に答えるのを助けるかもしれません – DavidW

+0

もう1つの考え:' c'は実行し、空のキューを見つけて、 (または誤解ですか?) – DavidW