25

マルチプロセッシングのプールを使用してプロセスのグループを実行しようとしています。各プロセスはグリーンレットの gevent プールを実行します。この理由は、多くのネットワーク アクティビティだけでなく、多くの CPU アクティビティがあるためです。そのため、帯域幅とすべての CPU コアを最大化するには、複数のプロセスと gevent の非同期モンキー パッチが必要です。マルチプロセッシングのマネージャーを使用して、プロセスが処理するデータを取得するためにアクセスするキューを作成しています。

コードの簡略化されたフラグメントを次に示します。

import multiprocessing

from gevent import monkey
monkey.patch_all(thread=False)

manager = multiprocessing.Manager()
q = manager.Queue()

これが生成する例外は次のとおりです。

Traceback (most recent call last):
  File "multimonkeytest.py", line 7, in <module>
    q = manager.Queue()
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 667, in temp
    token, exp = self._create(typeid, *args, **kwds)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 565, in _create
    conn = self._Client(self._address, authkey=self._authkey)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 175, in Client
    answer_challenge(c, authkey)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 409, in answer_challenge
    message = connection.recv_bytes(256)         # reject large message
 IOError: [Errno 35] Resource temporarily unavailable

これは、通常のソケット モジュールと gevent のソケット モジュールの動作の違いによるものだと思います。

サブプロセス内でモンキーパッチを実行すると、キューは正常に作成されますが、サブプロセスがキューから get() を実行しようとすると、非常によく似た例外が発生します。サブプロセスで多数のネットワーク要求を実行するため、ソケットにモンキーパッチを適用する必要があります。

私のバージョンのgeventは最新だと思います:

>>> gevent.version_info
(1, 0, 0, 'alpha', 3)

何か案は?

4

5 に答える 5

18

use monkey.patch_all(thread=False, socket=False)

I have run into the same issue in a similar situation and tracked this down to line 115 in gevent/monkey.py under the patch_socket() function: _socket.socket = socket.socket. Commenting this line out prevents the breakage.

This is where gevent replaces the stdlib socket library with its own. multiprocessing.connection uses the socket library quite extensively, and is apparently not tolerant to this change.

Specifically, you will see this in any scenario where a module you import performs a gevent.monkey.patch_all() call without setting socket=False. In my case it was grequests that did this, and I had to override the patching of the socket module to fix this error.

于 2013-02-06T18:50:08.823 に答える
9

gevent のコンテキストでマルチプロセッシングを適用すると、残念ながら問題が発生することが知られています。ただし、あなたの論理的根拠は合理的です(「ネットワークアクティビティが多いだけでなく、CPUアクティビティも多い」)。よろしければ、http://gehrcke.de/gipcをご覧ください。これは主にユースケース用に設計されています。gipc を使用すると、gevent を完全に認識するいくつかの子プロセスを簡単に生成し、パイプを介して相互に、および/または親と協調的に対話させることができます。

ご不明な点がございましたら、お気軽にお問い合わせください。

于 2013-02-11T20:06:17.917 に答える
2

元の Queue を使用する場合、コードはモンキー パッチ ソケットでも正常に動作します。

import multiprocessing

from gevent import monkey
monkey.patch_all(thread=False)

q= multiprocessing.Queue()
于 2013-10-20T08:22:03.913 に答える
1

代替の Nose Multiprocess プラグインを作成しました。これは、あらゆる種類のクレイジーな Gevent ベースのパッチでうまく機能するはずです。

https://pypi.python.org/pypi/nose-gevented-multiprocess/

https://github.com/dvdotsenko/nose_gevent_multiprocess

  • multiprocess.forkワーカー プロセスをプレーンに切り替えsubprocess.popenます (モジュール レベルで誤って共有されたオブジェクトの問題を修正します)。
  • マスターからクライアントへの RPC のために、multiprocess.Queue から HTTP 経由の JSON-RPC に切り替えました
  • これにより、理論的にはテストを複数のマシンに分散できるようになりました
于 2014-01-06T10:00:25.813 に答える
1

提供されたコードは、Windows 7 で動作します。

編集:

Ubuntu 11.10 VPS でコードを試したところ、同じエラーが発生したため、以前の回答を削除しました。

Eventletにもこの問題があるようです

于 2011-12-30T13:21:55.510 に答える