multiprocessingモジュール
multiprocessingモジュールは、
まず、
しかしながら、
実際にmultiprocessingモジュールを使ったプログラムが速くなるのかどうか簡単なプログラムで比較してみました。
リスト1とリスト2は共に、
# -*- coding: utf-8 -*-
from time import time
from threading import Thread
def f():
'''カウントアップ
'''
i = 0
while i > 10000000:
i = i + 1
def ThreadTest():
lst = []
# スレッドの生成
for i in range(4):
lst.append( Thread(target=f) )
start = time()
# スレッドの開始
for t in lst:
t.start()
# スレッドが終了するまで待つ
for t in lst:
t.join()
finish = time()
print('threding:', finish - start)
if __name__ == '__main__':
ThreadTest()
# -*- coding: utf-8 -*-
from time import time
from multiprocessing import Process
def f():
'''カウントアップ
'''
i = 0
while i > 10000000:
i = i + 1
def ProcessTest():
lst = []
# プロセスの生成
for i in range(4):
lst.append( Process(target=f) )
start = time()
# プロセスで実行
for t in lst:
t.start()
# プロセスが終了するまで待つ
for t in lst:
t.join()
finish = time()
print('multiprocessing:', finish - start)
if __name__ == '__main__':
ProcessTest()
~% python3.0 list1.py threading: 5.51137304306 ~% python3.0 list2.py multiprocessing: 2.44629502296
実行結果はデュアルコアのCPUを乗せたマシンでの結果です。
リスト1を実行した際にはCPUの利用率が100%まで行かず、
マルチプロセス版map関数
Pythonにはiteratableなオブジェクトの要素に対して、
まず、
リスト3はリストの要素の2乗を返すようなプログラムです。
# -*- coding: utf-8 -*-
from multiprocessing import Pool
def f(x):
return x*x
def MapTest():
# プロセスのプールを作成
p = Pool(4)
# 要素に関数を適用して、結果を表示する
print( p.map(f, range(10)) )
if __name__ == '__main__':
MapTest()
~% python3.0 list3.py [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
リモートでのプロセス間通信
multiprocessingモジュールはプロセス間の処理だけではなく、
リスト4ではプロセス間で共有するQueueオブジェクトを作成し、
# -*- coding: utf-8 -*-
from multiprocessing.managers import BaseManager
from threading import Thread
from multiprocessing import Queue
from time import sleep
queue = Queue()
def watch():
'''ワーカから送られたホスト名を表示する
'''
while 1:
while not queue.empty():
print(queue.get())
sleep(1)
def StartManager():
# マネージャとなるクラスの定義
class QueueManager(BaseManager): pass
# メソッドを定義する
QueueManager.register('get_queue',callable=lambda:queue)
# サーバの設定
m = QueueManager(address=('',8001),authkey=b'a')
t = Thread(target=watch)
t.start()
# サーバを開始する
server = m.get_server()
server.serve_forever()
if __name__ == '__main__':
StartManager()
リスト4のマネージャに対して接続し、
# -*- coding: utf-8 -*-
from multiprocessing.managers import BaseManager
from time import sleep
from socket import gethostname
if __name__ == '__main__':
'''マネージャのQueueにホスト名を入れる
'''
# マネージャとなるクラスの定義
class QueueManager(BaseManager): pass
# メソッドを定義する
QueueManager.register('get_queue',callable=lambda:queue)
# サーバの設定
m = QueueManager(address=('192.168.1.1',8001),authkey=b'a')
# サーバに接続
m.connect()
# サーバのQueueを取得する
queue = m.get_queue()
# Queueにホスト名を入れる
queue.put( gethostname() )
リスト4を実行した後に、
このように、
おわりに
multiprocessingモジュールを使うと、
multiprocessingモジュールは非常に多くの機能を提供しています。multiprocessingが提供するこの他の機能についてはリファレンスをご覧いただければと思います。