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进程在什么CPU核上运行?_Python_Multithreading_Python 3.x_Multiprocessing - Fatal编程技术网

我的Python进程在什么CPU核上运行?

我的Python进程在什么CPU核上运行?,python,multithreading,python-3.x,multiprocessing,Python,Multithreading,Python 3.x,Multiprocessing,设置 我用Python(在Windows PC上)编写了一个相当复杂的软件。我的软件基本上启动了两个Python解释器外壳。当您双击main.py文件时,第一个shell启动。在该shell中,其他线程以以下方式启动: # Start TCP_thread TCP_thread = threading.Thread(name = 'TCP_loop', target = TCP_loop, args = (TCPsock,)) TCP_thread.start()

设置

我用Python(在Windows PC上)编写了一个相当复杂的软件。我的软件基本上启动了两个Python解释器外壳。当您双击
main.py
文件时,第一个shell启动。在该shell中,其他线程以以下方式启动:

    # Start TCP_thread
    TCP_thread = threading.Thread(name = 'TCP_loop', target = TCP_loop, args = (TCPsock,))
    TCP_thread.start()

    # Start UDP_thread
    UDP_thread = threading.Thread(name = 'UDP_loop', target = UDP_loop, args = (UDPsock,))
    TCP_thread.start()
p = subprocess.Popen(['python', mySubprocessPath], shell=True)
Main_线程
启动一个
TCP_线程
和一个
UDP_线程
。尽管这些线程是独立的,但它们都在一个Python shell中运行

主线程也启动一个子进程。这是通过以下方式完成的:

    # Start TCP_thread
    TCP_thread = threading.Thread(name = 'TCP_loop', target = TCP_loop, args = (TCPsock,))
    TCP_thread.start()

    # Start UDP_thread
    UDP_thread = threading.Thread(name = 'UDP_loop', target = UDP_loop, args = (UDPsock,))
    TCP_thread.start()
p = subprocess.Popen(['python', mySubprocessPath], shell=True)
从Python文档中,我了解到这个子流程在一个单独的Python解释器会话/shell中同时运行(!)。此子流程中的
主线程
完全专用于我的GUI。GUI为其所有通信启动一个
TCP\u线程

我知道事情变得有点复杂。因此,我在此图中总结了整个设置:


关于这个设置,我有几个问题。我将在下面列出:

问题1[已解决]

Python解释器一次只使用一个CPU核来运行所有线程,这是真的吗?换句话说,
Python解释器会话1
(图中)是否会在一个CPU内核上运行所有3个线程(
主线程
TCP线程
UDP线程

回答:是的,这是真的。GIL(全局解释器锁)确保所有线程一次在一个CPU内核上运行

问题2[尚未解决]

我有办法跟踪它是哪个CPU核心吗

问题3[部分解决]

对于这个问题,我们忘记了线程,但我们主要关注Python中的子进程机制。启动一个新的子流程意味着启动一个新的Python解释器实例。这是正确的吗

回答:是的,这是正确的。起初,对于以下代码是否会创建一个新的Python解释器实例存在一些混淆:

    # Approach 1(a)
    p = subprocess.Popen(['python', mySubprocessPath], shell = True)

    # Approach 1(b) (J.F. Sebastian)
    p = subprocess.Popen([sys.executable, mySubprocessPath])

    # Approach 2
    p = multiprocessing.Process(target=foo, args=(q,))
# Approach 1(a)
p = subprocess.Popen(['python', mySubprocessPath], shell = True)

# Approach 1(b) (J.F. Sebastian)
p = subprocess.Popen([sys.executable, mySubprocessPath])

# Approach 2
p = multiprocessing.Process(target=foo, args=(q,))
问题已经澄清。这段代码实际上启动了一个新的Python解释器实例

Python是否足够聪明,可以让单独的Python解释器实例在不同的CPU核心上运行?有没有一种方法可以追踪哪一种,也许还有一些零星的打印语句

问题4[新问题]

社区讨论提出了一个新问题。在生成新进程(在新的Python解释器实例中)时,显然有两种方法:


第二种方法有一个明显的缺点,就是它只针对一个函数,而我需要打开一个新的Python脚本。无论如何,这两种方法在实现什么方面相似吗?

因为您使用的是建立在
线程
上的
线程
模块。如文档所示,它使用操作系统的“POSIX线程实现”pthread

  • 线程由操作系统而不是Python解释器管理。因此,答案将取决于系统中的pthread库。然而,CPython使用GIL来防止多个线程同时执行Python字节码。因此,它们将被顺序化。但它们仍然可以分离到不同的核心,这取决于pthread libs
  • 简单地使用调试器并将其附加到python.exe。例如,
  • 与问题1类似,新流程由操作系统管理,可能运行在不同的核心上。使用调试器或任何进程监视器查看它。有关更多详细信息,请转到
    CreatProcess()
    文档

  • 1、2:您有三个真正的线程,但在CPython中,它们受到GIL的限制,因此,假设它们运行的是纯python代码,您将看到CPU使用情况,就好像只使用了一个内核一样

    3:正如gdlmx所说的,由操作系统选择运行线程的核心, 但如果您确实需要控制,您可以使用 本机API通过
    ctypes
    。由于您使用的是Windows,因此如下所示:

    # This will run your subprocess on core#0 only
    p = subprocess.Popen(['python', mySubprocessPath], shell = True)
    cpu_mask = 1
    ctypes.windll.kernel32.SetProcessAffinityMask(p._handle, cpu_mask)
    
    这里我使用private
    Popen.\u handle
    来简化。清洁的方法是
    OpenProcess(p.tid)

    是的,
    子流程
    像其他流程一样运行python

    Q:Python解释器一次只使用一个CPU核来运行所有线程,这是真的吗


    不。GIL和CPU关联性是不相关的概念。GIL可以在阻塞I/O操作期间释放,而阻塞I/O操作是C扩展中CPU密集型的长时间计算

    如果GIL上有螺纹堵塞;它可能不在任何CPU核上,因此可以公平地说,纯Python多线程代码在CPython实现上一次只能使用一个CPU核

    Q:换句话说,Python解释器会话1(图中)是否会在一个CPU内核上运行所有3个线程(主线程、TCP线程和UDP线程)

    我不认为CPython隐式地管理CPU亲和力。它很可能依赖操作系统调度程序来选择线程的运行位置。Python线程是在真正的OS线程之上实现的

    Q:或者Python解释器能够将它们分布到多个核心上吗

    要了解可用CPU的数量,请执行以下操作:

    >>> import os
    >>> len(os.sched_getaffinity(0))
    16
    
    同样,线程是否调度在不同的CPU上并不取决于Python解释器

    Q:假设问题1的答案是“多核”,我是否有办法跟踪每个线程在哪个核上运行,也许是使用一些零星的打印语句?如果问题1的答案是“只有一个核心”,我是否有办法追踪它是哪一个

    我想,一个特定的CPU可能会从一个时隙切换到另一个时隙。你可以。在我的机器上:

    对于当前的可移植解决方案,请查看是否公开此类信息

    你可以去洗手间
    # Approach 1(a)
    p = subprocess.Popen(['python', mySubprocessPath], shell = True)
    
    # Approach 1(b) (J.F. Sebastian)
    p = subprocess.Popen([sys.executable, mySubprocessPath])
    
    # Approach 2
    p = multiprocessing.Process(target=foo, args=(q,))