Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.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/6/multithreading/4.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
Python 多处理多线程GIL?_Python_Multithreading_Multiprocessing - Fatal编程技术网

Python 多处理多线程GIL?

Python 多处理多线程GIL?,python,multithreading,multiprocessing,Python,Multithreading,Multiprocessing,所以,几天以来,我在python上做了很多关于多处理和多线程的研究,我对很多事情感到非常困惑。很多时候,我看到有人在谈论GIL,它不允许Python代码在多个cpu核上执行,但当我编写一个创建多个线程的程序时,我可以看到多个cpu核处于活动状态 第一个问题:吉尔到底是什么?它有用吗?我认为,当一个进程在多个cpu上创建太多线程时,操作系统分布式任务就会发生。我说得对吗 另外,我想利用我的CPU。我考虑创建和cpu核心一样多的进程,在这个过程中,每个进程创建和cpu核心一样多的线程。我走对了吗?关

所以,几天以来,我在python上做了很多关于多处理和多线程的研究,我对很多事情感到非常困惑。很多时候,我看到有人在谈论GIL,它不允许Python代码在多个cpu核上执行,但当我编写一个创建多个线程的程序时,我可以看到多个cpu核处于活动状态

第一个问题:吉尔到底是什么?它有用吗?我认为,当一个进程在多个cpu上创建太多线程时,操作系统分布式任务就会发生。我说得对吗


另外,我想利用我的CPU。我考虑创建和cpu核心一样多的进程,在这个过程中,每个进程创建和cpu核心一样多的线程。我走对了吗?

关于什么是全局解释器锁(GIL),有很多答案。答案中隐藏着对Python“字节码”的提及,这是问题的核心。编译程序时,输出是字节码,即虚拟“Python”计算机的低级计算机指令,由Python解释器进行解释。当解释器执行字节码时,它通过获取全局解释器锁来序列化执行。这意味着两个线程不能在两个不同的内核上同时执行字节码。但这也是防止这两个线程在更新同一列表时相互干扰的原因。这也意味着没有实现真正的多线程。但这是否意味着没有理由使用线程?不以下是线程仍然有用的几种情况:

  • 对于某些操作,解释器将释放吉尔,即在执行I/O时,以一个示例为例,您想从不同的网站获取大量URL。大部分时间都花在等待请求发出后返回响应上,这种等待可能会重叠,即使必须连续地制定请求
  • 许多Python函数和模块是用C语言实现的,不受任何GIL限制。
    numpy
    模块就是这样一个高度优化的包

  • 因此,当任务不是cpu密集型任务时,最好使用线程,即它们需要大量等待i/O完成,或者需要大量睡眠等。

    关于全局解释器锁(GIL)是什么,有一些答案。答案中隐藏着对Python“字节码”的提及,这是问题的核心。编译程序时,输出是字节码,即虚拟“Python”计算机的低级计算机指令,由Python解释器进行解释。当解释器执行字节码时,它通过获取全局解释器锁来序列化执行。这意味着两个线程不能在两个不同的内核上同时执行字节码。但这也是防止这两个线程在更新同一列表时相互干扰的原因。这也意味着没有实现真正的多线程。但这是否意味着没有理由使用线程?不以下是线程仍然有用的几种情况:

  • 对于某些操作,解释器将释放吉尔,即在执行I/O时,以一个示例为例,您想从不同的网站获取大量URL。大部分时间都花在等待请求发出后返回响应上,这种等待可能会重叠,即使必须连续地制定请求
  • 许多Python函数和模块是用C语言实现的,不受任何GIL限制。
    numpy
    模块就是这样一个高度优化的包

  • 因此,当任务不是cpu密集型任务时,最好使用线程,即任务需要大量等待i/O完成,或者需要大量睡眠等。首先,GIL只能确保在任何给定时间只运行一条cpython字节码指令。它不关心哪个CPU内核运行指令。这就是操作系统内核的工作

    因此,回顾一下你的问题:

  • 吉尔只是一段代码。CPython虚拟机是首先将代码编译成CPython字节码的过程,但它的正常工作是解释CPython字节码。GIL是一段代码,它确保无论运行多少个线程,一次只运行一行字节码。Cpython字节码指令构成了虚拟机堆栈。因此,在某种程度上,GIL将确保在任何给定的时间点只有一条线程持有GIL。(此外,它还可以不断释放其他线程的GIL,而不会使它们饥饿。)
  • 现在来谈谈你真正的困惑。您提到,当您运行一个具有多个线程的程序时,您可以看到多个(可能是全部)CPU内核启动。因此,我做了一些实验,发现您的发现是正确的(这是显而易见的),但在非线程版本中的行为也类似

    def do_nothing(i):
        time.sleep(0.0001)
        return i*2
    
    ThreadPool(20).map(do_nothing, range(10000))
    
    第一个是多线程的,第二个不是。当您比较这两个程序的CPU使用率时,您会发现在这两种情况下都会触发多个CPU核。所以你所注意到的,虽然是正确的,但与GIL或线程无关。CPU在多个内核中的高使用率只是因为OS内核将根据可用性将代码的执行分配给不同的内核

    最后一个问题更像是一个实验性的问题,因为不同的程序有不同的CPU/io使用率。您只需了解创建线程和进程的成本以及GIL&PVM的工作,并优化线程和进程的数量,以获得最大的性能


    您可以阅读David Beazley的文章,了解多线程如何使代码性能更差(或更好)。

    首先,GIL只确保在任何给定的t上只运行一条cpython字节码指令
    def do_nothing(i):
        time.sleep(0.0001)
        return i*2
    
    [do_nothing(i) for i in  range(10000)]