7

私はかなり標準的な Threading.Event を使用しています: メインスレッドは、実行されるループ内のポイントに到達します:

event.wait(60)

他のブロックは、応答が利用可能になるまで要求をブロックし、次のことを開始します。

event.set()

メインスレッドが 40 秒間選択することを期待しますが、そうではありません。Python 2.7 ソース Lib/threading.py から:

# Balancing act:  We can't afford a pure busy loop, so we
# have to sleep; but if we sleep the whole timeout time,
# we'll be unresponsive.  The scheme here sleeps very
# little at first, longer as time goes on, but never longer
# than 20 times per second (or the timeout time remaining).
endtime = _time() + timeout
delay = 0.0005 # 500 us -> initial delay of 1 ms
while True:
   gotit = waiter.acquire(0)
   if gotit:
       break
   remaining = endtime - _time()
   if remaining <= 0:
       break
   delay = min(delay * 2, remaining, .05)
   _sleep(delay)

得られるのは、500us ごとに実行される select syscall です。これにより、選択ループが非常にタイトになり、マシンにかなりの負荷がかかります。

バランスをとる行為が含まれる理由と、それがファイル記述子を待機しているスレッドと異なる理由を説明してください。

第二に、そのようなタイトなループなしで、ほとんどスリープ状態のメインスレッドを実装するより良い方法はありますか?

4

2 に答える 2

3

threading私は最近同じ問題に見舞われ、モジュール内のこの正確なコード ブロックまで追跡しました。

最悪だ。

解決策は、threading モジュールをオーバーロードするかpython3、実装のこの部分が修正された に移行することです。

私の場合、python3 に移行するのは大変な作業だったので、前者を選びました。私がしたことは:

  1. へのインターフェイスを備えたクイック.soファイルを ( を使用して) 作成しました。これには、対応する関数を呼び出す python 関数が含まれており、 . 具体的には、関心のあるタスクに最も関連する関数はpthread_mutex_timedlockです。cythonpthreadpthread_mutex_*libpthread
  2. 新しいthreading2モジュールを作成しました (そしてimport threading、コードベースのすべての行を に置き換えましたimport threading2)。では、関連するすべてのクラス( 、、) と、よく使用するクラス (および)threading2を再定義しました。このクラスは関数を使用して完全に再実装されましたが、残りははるかに簡単でした。元のクラス (例: ) を単純にサブクラス化し、オーバーライドして新しい型を作成しました。残りはうまくいきました。threadingLockConditionEventQueueQueuePriorityQueueLockpthread_mutex_*threading.Event__init__Lock

新しいLockタイプの実装は、 の元の実装と非常に似ていましたが、のモジュールで見つけたコードにthreading基づいて の新しい実装を作成しました(当然のことながら、上記の「balancing act」ブロックよりもはるかに単純です)。この部分はかなり簡単でした。acquirepython3threading

(ちなみに、私の場合の結果は、大規模なマルチスレッド プロセスの 30% の高速化でした。予想以上でした。)

于 2014-03-11T17:51:41.550 に答える
2

私はあなたに完全に同意します、これは不自由です。

現在、タイムアウトなしの単純な選択呼び出しに固執しており、以前に作成されたパイプをリッスンしています。ウェイクアップは、パイプに文字を書き込むことによって行われます。

Gunicorn のこのスリープおよびウェイクアップ関数を参照してください。

于 2013-03-24T15:53:10.697 に答える