from threading import Thread
def countdown(start, end):
while end > start:
end -= 1
def multi_thread(n):
t1 = Thread(target=countdown, args=(0, n // 2))
t2 = Thread(target=countdown, args=(n // 2, n))
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
import timeit
import sys
sys.setswitchinterval(1)
print(timeit.timeit("""import gil;gil.multi_thread(10000000);""", number=1))
# 1.07s
sys.setswitchinterval(0.001)
print(timeit.timeit("""import gil;gil.multi_thread(10000000);""", number=1))
# 1.09s
看完NewGIL.pdf ,我认为小的间隔会导致更多的线程 sleep /唤醒操作,然后总的执行时间应该更长。我错了吗?
测试环境:四核Ubuntu16.04 python3.5
请您参考如下方法:
请注意,您的整个任务只需要大约 1 秒。因此,对于 0.001 秒的切换间隔,只有大约 1/0.001 = 一千次切换总计。每个开关的成本(以“C 速度”发生)更自然地以微秒而不是毫秒来衡量,因此与 1 秒的总耗时相比,其中一千个开关仍然便宜。
要查看更多效果,请尝试将开关间隔设置为 1e-6。
在现实生活中,线程切换的实际成本更多的是相关成本:线程获得足够的时间来填充硬件指令和数据缓存,然后被切换出去,新线程遭受缓存起初在各个层面上都错过了。您的示例没有任何这些成本(每个线程使用的代码和数据相对较小,并且两个线程的内容甚至可以同时放入 L1 缓存中)。
