Hatena::ブログ(Diary)

diaの備忘録

2009年09月21日

PythonでCPUを遊ばせたくない!

g:subtech:id:mala:20090920:1253447692にて、すばらしいスレッド関係のまとめが記載されていました。ちょうど、今取り組んでいる研究に必要なことなのでなんてタイムリーなんだ!と思いました。GJ!

さて、その中で気になったのがPythonでGILを無くす(回避する?)仕組みといういうところ。研究で使うため、PythonでCPUを遊ばせないようにするにはどうするのかということを調べていました。私が調べた限りでは、ちょっと前まではParallel Python、最近は2.6以降から導入されたmultiprocessingを使う、と認識しています。CPUを遊ばせたくない場合は、皆様はどのようにしているのでしょうか*1

ちなみに私は、multiprocessingを使っています。用途が並列処理なので主にPoolを使っています。下記に私が検討に使ったサンプルを記載します。Poolを使ってみようという方の参考になれば幸いです。


ソース*2
#!/usr/bin/env python
# coding: utf-8
from multiprocessing import Pool, cpu_count
import os
from time import sleep, time
from datetime import datetime

def show_pid(v):
	print('pid: %d, %s, %d' % (os.getpid(), datetime.now(), v))
	sleep(1)
	return v * v 

def main():
	print('pid: %d' % os.getpid())
	c = cpu_count()
	print('num of cpu: %d' % c)
	print('')
	
	pool = Pool(c)
	
	print("### apply_async ###")
	t = time()	
	results = []
	for i in range(10):
		results.append( pool.apply_async(show_pid, (i,)) )
	print([result.get() for result in results])
	print("time: %f sec" % (time() - t))
	print('')
	
	print("### apply ###")
	t = time()
	results = []
	for i in range(10):
		results.append( pool.apply(show_pid, (i,)) )
	print(results)
	print("time: %f sec" % (time() - t))
	print('')
	
	print("### map_async ###")
	t = time()
	result = pool.map_async(show_pid, range(10))
	print([val for val in result.get()])
	print("time: %f sec" % (time() - t))
	print('')

	print("### map ###")
	t = time()
	result = pool.map(show_pid, range(10))
	print([val for val in result])
	print("time: %f sec" % (time() - t))
	print('')

if __name__ == '__main__':
	main()
結果
pid: 3263
num of cpu: 2

### apply_async ###
pid: 3265, 2009-09-11 17:37:44.580676, 0
pid: 3266, 2009-09-11 17:37:44.581427, 1
pid: 3265, 2009-09-11 17:37:45.581717, 2
pid: 3266, 2009-09-11 17:37:45.582424, 3
pid: 3265, 2009-09-11 17:37:46.582206, 4
pid: 3266, 2009-09-11 17:37:46.582897, 5
pid: 3265, 2009-09-11 17:37:47.582650, 6
pid: 3266, 2009-09-11 17:37:47.583289, 7
pid: 3265, 2009-09-11 17:37:48.583273, 8
pid: 3266, 2009-09-11 17:37:48.583694, 9
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
time: 5.004885 sec

### apply ###
pid: 3265, 2009-09-11 17:37:49.584509, 0
pid: 3266, 2009-09-11 17:37:50.585419, 1
pid: 3265, 2009-09-11 17:37:51.586743, 2
pid: 3266, 2009-09-11 17:37:52.588462, 3
pid: 3265, 2009-09-11 17:37:53.589407, 4
pid: 3266, 2009-09-11 17:37:54.590448, 5
pid: 3265, 2009-09-11 17:37:55.591413, 6
pid: 3266, 2009-09-11 17:37:56.592293, 7
pid: 3265, 2009-09-11 17:37:57.593378, 8
pid: 3266, 2009-09-11 17:37:58.594204, 9
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
time: 10.010553 sec

### map_async ###
pid: 3265, 2009-09-11 17:37:59.595753, 0
pid: 3266, 2009-09-11 17:37:59.595889, 2
pid: 3265, 2009-09-11 17:38:00.595960, 1
pid: 3266, 2009-09-11 17:38:00.596067, 3
pid: 3266, 2009-09-11 17:38:01.596499, 4
pid: 3265, 2009-09-11 17:38:01.596748, 6
pid: 3266, 2009-09-11 17:38:02.596684, 5
pid: 3265, 2009-09-11 17:38:02.596888, 7
pid: 3266, 2009-09-11 17:38:03.597184, 8
pid: 3266, 2009-09-11 17:38:04.597359, 9
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
time: 6.003107 sec

### map ###
pid: 3265, 2009-09-11 17:38:05.598495, 0
pid: 3266, 2009-09-11 17:38:05.598840, 2
pid: 3265, 2009-09-11 17:38:06.598674, 1
pid: 3266, 2009-09-11 17:38:06.598975, 3
pid: 3265, 2009-09-11 17:38:07.599322, 4
pid: 3266, 2009-09-11 17:38:07.599523, 6
pid: 3265, 2009-09-11 17:38:08.599601, 5
pid: 3266, 2009-09-11 17:38:08.599770, 7
pid: 3265, 2009-09-11 17:38:09.600180, 8
pid: 3265, 2009-09-11 17:38:10.600477, 9
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
time: 6.002964 sec

*1:Rubyは最近手をつけていないけど、Rubyではどうやれるのかなぁ。後で調べてみよう

*2d:id:nullpobug:20090101:1230752701のものをかなり流用しました。検討するとき助かりました。ありがとうございます。