我的Python进程在什么CPU核上运行?
设置 我用Python(在Windows PC上)编写了一个相当复杂的软件。我的软件基本上启动了两个Python解释器外壳。当您双击我的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()
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)
这里我使用privatePopen.\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,))