【发布时间】:2015-04-16 05:59:50
【问题描述】:
这个问题是我上一个问题 (Threading in Python - What am I missing?) 的续集。
感谢指出线程问题所在的人。这个问题终于解决了,我启用了信号量,并且惊讶地发现仅仅启用它们就将程序的执行时间从几分之一秒缩短到了 4 秒!哇... 3 秒仅 80000 次迭代似乎慢得可怕,即使考虑到碰撞也是如此。
具体时间:
Without semaphore 0.0167980194092 s
With semaphore 2.76963996887 s
代码如下:
import threading
import time
import random
turnstile_names = ["N", "E", "S", "W"]
count = 0
sem = threading.Semaphore(1)
class Incrementer(threading.Thread):
def __init__(self, id):
threading.Thread.__init__(self)
self.id = id
def run(self):
global count, sem
for i in range(20000):
sem.acquire()
count = count + 1
sem.release()
def main():
random.seed(507129)
incrementers = [Incrementer(name) for name in turnstile_names]
for incrementer in incrementers:
incrementer.start()
# We're running!
for incrementer in incrementers:
incrementer.join()
print count
return 0
if __name__ == '__main__':
main()
【问题讨论】:
-
得到
80000为count,总是,没有Semaphore? -
“即使考虑到冲突” - 冲突是轻描淡写,这是顺序执行(增加了开销)。
-
80,000 个锁在 3 秒内。那是 0.4 毫秒/锁。对于真正工作的线程来说并没有那么糟糕,但是是的,线程同步不是免费的。您可以通过使用线程本地计数器并在最后汇总这些计数器来完全避免这种情况。
-
我已经使用 Python 3.4.2 在我的 2700K @ 4.6 GHz 上为您的代码计时。每次运行我得到 0.27 秒。然而,这不是你的问题。 GIL 确保在任何时候只有一个线程运行。在 Python 中创建执行繁重 CPU 处理的线程是没有实际意义的。线程仅在您具有 I/O 绑定工作负载时才有用。
-
@Thilo:感谢您的回复。0.4ms 在 3GHz 处理器上是永恒的。我只是做了这个例子,因为它是一个经典的信号量演示 - 一个公共计数器的递增是重点。
标签: python multithreading performance semaphore