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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

7555閲覧

Python スレッド上におけるリストへの要素の追加について

pipopa

総合スコア12

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2016/08/21 09:01

###前提・実現したいこと
Python3.5においてmultiprocessingライブラリを使ったスレッドにてリストの要素を追加したいです。

###該当のソースコードと実行結果

Python3.5

1from multiprocessing import Process 2 3class Test_Process(Process): 4 def __init__(self, l): 5 Process.__init__(self) 6 self.l = l 7 def run(self): 8 for i in range(15): 9 self.l.append(i) 10 print('self.l = ', end='') 11 print(self.l) 12 return 13 14r = [29,31] 15t = Test_Process(r) 16t.start() 17t.join() 18print('r = ', end='') 19print(r) 20

上記のコードを実行すると以下のように出力されました。

self.l = [29, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] r = [29, 31]

想定では r の中身は self.l と同じになると思ったのですが上手く動きませんでした。

###試したこと
以下に示すスレッドを使わない普通のクラスを使ったコードは実行すると r に対して要素が追加され思ったとおりになりました。

class Test_Class(object): def __init__(self, l): self.l = l def test_method(self): for i in range(15): self.l.append(i) print('self.l = ', end='') print(self.l) return r = [29,31] t = Test_Class(r) t.test_method() print('r = ', end='') print(r)

実行結果

self.l = [29, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] r = [29, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

スレッドを使ったほうではなぜ動かないのかがわからないので原因を教えてほしいです。

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

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

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

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

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

argius

2016/08/21 10:55

multiprocessingはスレッドとは異なりますのでご注意ください。
guest

回答1

0

ベストアンサー

複数プロセス間で情報をやりとりする場合、明示的に共有の操作を行う必要があります。

元のコードの場合、渡したリストは別のプロセスが参照する時にオブジェクト自体がコピーされて別のもの(インスタンス)になってしまうので、別プロセスで変更した結果は呼び出し元のrには反映されません。

一例として、Managerを使う例を示します。

lang

1from multiprocessing import Process, Manager 2 3# 略 4 5manager = Manager() 6r = manager.list([29, 31]) # 共有可能なリスト 7t = Test_Process(r) 8 9# 略

こうすると、複数プロセス間で共有するリストが生成され、結果が共有できるようになります。

17.2.1.5. プロセス間での状態の共有 - 17.2. multiprocessing — プロセスベースの並列処理 — Python 3.5.1 ドキュメント
http://docs.python.jp/3.5/library/multiprocessing.html#sharing-state-between-processes

関連する質問:
Python - Pythonのmultiprocessing.Processでのグローバル変数の共有について(21122)|teratail
https://teratail.com/questions/21122

投稿2016/08/21 10:46

argius

総合スコア9388

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

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

pipopa

2016/08/21 11:50

回答ありがとうございます。訂正了解しました。 multiprocessingは別のメモリに作業場所が確保されて、必要なデータはコピーがとられるので、共有したいデータは明示する必要があるということですね。公式ドキュメントはしっかり読むようにします。 前回に続き回答して下さりありがとうございます。
argius

2016/08/21 12:10

補足です。 multiprocessingは、マルチプロセスを使います。 メモリー空間というのはプロセスごとに持っているものですので、通常の1つのプロセスだったら共有できるような場面でも、マルチプロセスの場合はプロセスを作った時点のメモリーがコピーされた後で切り離されてしまいますので、独立したプロセス間では明示的にデータの連携を行わないとデータを共有できません。 Managerはその辺を上手くやってくれる仕組みです。 以上のことも含めてマルチプロセスはマルチスレッドに比べるとリソースを多く必要としますので、 非同期処理を行うだけならthreadingを使うことも検討してみて下さい。 マルチスレッドの場合も同時に読み書きする場合の考慮が必要ですが、マルチプロセスほどではありません。
pipopa

2016/08/21 12:35

補足ありがとうございます。 threadingの場合は同メモリ上で処理が行われるのでLock等を用いて、1つのスレッドしか読み書きできないようにすればよいのですね。 データの共有が必要のない独立した処理や計算の場合は、マルチプロセスのほうがマルチスレッドより速度が速くなるという認識であっていますでしょうか?
argius

2016/08/21 12:58

> threadingの場合は同メモリ上で処理が行われるのでLock等を用いて、1つのスレッドしか読み書きできないようにすればよいのですね。 はい、そうです。 ただ(キリが無いので簡単に...)ロックの方法にもいろいろあって、それによって処理速度を上げたりできます。 > データの共有が必要のない独立した処理や計算の場合は、マルチプロセスのほうがマルチスレッドより速度が速くなるという認識であっていますでしょうか? 処理の内容にもよりますが、 例えば以下の条件を満たしていれば速くなる可能性は高いと思います。 ・処理が十分長い(プロセス起動のオーバーヘッドの影響が少ない) ・コア数が十分にあり、処理を均等に各コアに分散させている ・各コアを使い切るような計算・処理をさせている Pythonのコードでは制御できないところも含みます。 Python本体がある程度うまくやってくれるはずですが、さすがに私もそれ以上はPythonのことは分からないので参考にとどめておいてください。
pipopa

2016/08/21 13:08

ありがとうございます。並列処理は複雑で難しいですね...。もっとよく勉強します。
yohhoy

2016/08/21 23:45 編集

参考までに:Pythonの場合はマルチスレッドがあまり役に立ちません。全てのスレッドは単一プロセッサコア上で実行されるので、マルチコアを使い切れません。Pythonで並列計算をしたければ、必然的にマルチプロセスを利用する事になります。(Pythonスレッドの主用途は非同期I/O向けです。)
argius

2016/08/21 16:31

to yohhoyさん フォローコメントありがとうございます。 そうだったんですね。 to pipopaさん ということで、 threadingも検討と言ってしまいましたが、明らかにマルチコアでの計算が要求される場合は、Pythonにおいてはそこまで検討しないで良いみたいですね。すみません。 前コメントは一般論として、ということでご容赦ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問