Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在python3中,很小的检查间隔不会降低CPU密集型多线程的速度?_Python_Python 3.x_Cpython_Gil - Fatal编程技术网

为什么在python3中,很小的检查间隔不会降低CPU密集型多线程的速度?

为什么在python3中,很小的检查间隔不会降低CPU密集型多线程的速度?,python,python-3.x,cpython,gil,Python,Python 3.x,Cpython,Gil,在阅读之后,我认为一个小的间隔将导致更多的线程睡眠/唤醒操作,然后总的执行时间应该更长。我错了吗 测试环境:四核Ubuntu16.04 python3.5。是的,你是对的。 较低的切换间隔意味着将有更频繁的针对GIL的条件轮询,以查看是否可以获得GIL。 由于GIL,我们无法并行运行线程,因此更频繁的上下文切换实际上会损害我们的性能 如果您想提高系统的性能,您必须使用解决方案。请注意,整个任务只需1秒左右。因此,如果开关间隔为0.001秒,那么总共只有大约1/0.001=1000个开关。每个开关

在阅读之后,我认为一个小的间隔将导致更多的线程睡眠/唤醒操作,然后总的执行时间应该更长。我错了吗

测试环境:四核Ubuntu16.04 python3.5。

是的,你是对的。 较低的切换间隔意味着将有更频繁的针对GIL的条件轮询,以查看是否可以获得GIL。 由于GIL,我们无法并行运行线程,因此更频繁的上下文切换实际上会损害我们的性能


如果您想提高系统的性能,您必须使用解决方案。

请注意,整个任务只需1秒左右。因此,如果开关间隔为0.001秒,那么总共只有大约1/0.001=1000个开关。每个开关的成本(以“C速度”发生)更自然地以微秒来衡量,而不是以毫秒来衡量,因此与总的1秒运行时间相比,一千个开关仍然便宜

要查看更多效果,请尝试将切换间隔设置为
1e-6

在现实生活中,线程切换的实际成本通常是相关的成本:一个线程获得足够的时间来填充硬件指令和数据缓存,然后被切换出去,新线程首先在不同级别上遭受缓存未命中。您的示例没有任何这些开销(每个线程使用的代码和数据相对较小,两个线程的内容甚至可以同时放在一级缓存中)

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