3

以下のコードは、http: //docs.python.org/2/library/queue.html にある Python の公式キューの例とほぼ同じです。

from Queue import Queue
from threading import Thread
from time import time
import sys

num_worker_threads = int(sys.argv[1])
source = xrange(10000)

def do_work(item):
    for i in xrange(100000):
        pass

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()

for item in source:
    q.put(item)

start = time()

for i in range(num_worker_threads):
    t = Thread(target=worker)
    t.daemon = True
    t.start()

q.join()

end = time()

print(end - start)

これらは、Xeon 12 コア プロセッサでの結果です。

$ ./speed.py 1
12.0873839855

$ ./speed.py 2
15.9101941586

$ ./speed.py 4
27.5713479519

ワーカーの数を増やすと応答時間が短縮されると予想していましたが、実際には増加しています。何度も実験を繰り返しましたが、結果は変わりませんでした。

明らかな何かが欠けていますか?または、Python キュー/スレッドがうまく機能しませんか?

4

2 に答える 2

18

ええ、GILに関するマキシムの権利です。しかし、ワーカーで何か価値のあることを行うとすぐに、状況はほとんどの場合変わります。スレッドで実行される典型的なことには、I/O を待機することや、スレッド切り替えが非常にうまく実行できるその他のことが含まれます。ワーカーで数を数えるだけでなく、スリープ状態での作業をシミュレートすると、状況が劇的に変化します。

#!/usr/bin/env python

from Queue import Queue
from threading import Thread
from time import time, sleep
import sys

num_worker_threads = int(sys.argv[1])
source = xrange(1000)

def do_work(item):
    for i in xrange(10):
        sleep(0.001)

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()

for item in source:
    q.put(item)

start = time()

for i in range(num_worker_threads):
    t = Thread(target=worker)
    t.daemon = True
    t.start()

q.join()

end = time()

これにより、次の結果が得られます。

for i in 1 2 3 4 5 6 7 8 9 10; do echo -n "$i "; ./t.py $i; done
1 11.0209097862
2 5.50820493698
3 3.65133094788
4 2.73591113091
5 2.19623804092
6 1.83647704124
7 1.57275605202
8 1.38150596619
9 1.23809313774
10 1.1111137867

ここに画像の説明を入力

于 2013-05-21T09:33:27.313 に答える