質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Q&A

解決済

1回答

2648閲覧

ProcessPoolExecutor(Python2.7) Queue error.

spike0726

総合スコア12

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

0グッド

0クリップ

投稿2018/05/29 04:54

Python2.7.12の環境で、concurrent.futures.ProcessPoolExecutor を使い
並列処理を実装しています。
(訳あって、multiprocessing の並列処理関数は使っていません。Queue関数は使用。)

Python

1class A(): 2 def __init__(self): 3 self.queue = multiprocessing.Queue(maxsize=1024) 4 5 6 def proc(): 7 todo = [] 8 proc_list = get_classes() # 処理をさせたいクラス群を取得 9 with concurrent.futures.ProcessPoolExecutor() as executor: 10 for p in proc_list: 11 future = executor.submit(p.func, self.queue) # ★ 12 todo.append(future) 13 14 for future in futures.as_completed(todo): 15 res = future.result()

上記のコードを実行すると★部分で以下のエラーが発生します。
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/queues.py", line 268, in _feed
send(obj)
File "/usr/lib/python2.7/multiprocessing/queues.py", line 77, in getstate
assert_spawning(self)
File "/usr/lib/python2.7/multiprocessing/forking.py", line 52, in assert_spawning
' through inheritance' % type(self).name
RuntimeError: Queue objects should only be shared between processes through inheritance

ProcessPoolExecutorをThreadPoolExecutorに変更するとエラーなく正常処理します。

以下の条件で回避方法がありましたらご教授下さい。
(a)マルチコアでもGlobal Interpreter Lock機構の制限を受けるThreadPoolExecutorは使わない
(b)multiprocessingの並列処理も使わない
(c)ProcessPoolExecutorまたは上記(a)(b)以外の手法で並列化を実現したい
(d)multiprocessing.Queueは、並列化する関数(p.func)で参照したいのでできれば使いたいが
使わなくても同等の機能(キュー機構)が使えればそちらでも構わない

よろしくお願い致します。
以上です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

骨が折れますが、リモートマネージャー経由でmultiprocessing.Queueオブジェクトを共有するのが現実的な回避方法かと。

https://docs.python.org/ja/3/library/multiprocessing.html#using-a-remote-manager

ProcessPoolExecutorでタスクをsubmitする側でリモートマネージャーのサーバを動かしてmultiprocessing.Queueオブジェクトを登録しておき、タスク側でリモートマネージャーのクライアントを使用してそのQueueオブジェクト(のProxyオブジェクト)を取得する流れになると思います。

  • GILフリー => CPythonでやるならマルチプロセス一択
  • マルチプロセス対応のキュー機構 => multiprocessing.Queue or 標準ライブラリ外の何か

なので、multiprocessingのマネージャー機構を使うことを勧めています。ProcessPoolExecutorではありませんが、Windows環境でもLockやValueをプロセス間で共有できたので、他の環境でも動くはずです。

あと余談ですが、concurrentパッケージを使うなら3.5や3.6あたりで試したほうが良いと思います。2.7のconcurrentパッケージはbackportですよね?

投稿2018/05/30 04:39

YouheiSakurai

総合スコア6142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

spike0726

2018/05/30 12:40

丁寧な回答ありがとうございます。 ご提案のmultiprocessingのマネージャー機構というのを使ってみます! また、Pythonのバージョンについては、開発環境の制限で、2.7に限定されています。 すみません、backportというのが理解できておりませんが、 concurrent.futures は、「pip install futures」でインストールしました。 以上、よろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問