- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
设置
我用 Python(在 Windows PC 上)编写了一个相当复杂的软件。我的软件基本上启动了两个 Python 解释器 shell。当您双击 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()
Main_thread
启动一个 TCP_thread
和一个 UDP_thread
。尽管它们是单独的线程,但它们都在一个 Python shell 中运行。
Main_thread
也启动一个子进程。这是通过以下方式完成的:
p = subprocess.Popen(['python', mySubprocessPath], shell=True)
从 Python 文档中,我了解到此子进程在单独的 Python 解释器 session /shell 中同时 (!) 运行。此子进程中的 Main_thread
完全专用于我的 GUI。 GUI 为其所有通信启动一个 TCP_thread
。
我知道事情变得有些复杂。因此,我在此图中总结了整个设置:
我有几个关于此设置的问题。我会在这里列出它们:
问题 1 [已解决]
Python 解释器是否一次只使用一个 CPU 内核来运行所有线程?换句话说,Python 解释器 session 1
(从图中)是否会运行所有 3 个线程(Main_thread
、TCP_thread
和 UDP_thread
) 在一个 CPU 内核上?
回答:是的,这是真的。 GIL(全局解释器锁)确保所有线程一次在一个 CPU 内核上运行。
问题 2 [尚未解决]
我有办法跟踪它是哪个 CPU 内核吗?
问题 3 [部分解决]
对于这个问题,我们忘记了 threads,但我们关注 Python 中的 subprocess 机制。启动一个新的子进程意味着启动一个新的 Python 解释器instance。这是正确的吗?
回答:是的,这是正确的。起初对于以下代码是否会创建新的 Python 解释器实例存在一些混淆:
p = subprocess.Popen(['python', mySubprocessPath], shell = True)
问题已得到澄清。这段代码确实启动了一个新的 Python 解释器实例。
Python 是否足够聪明,可以让单独的 Python 解释器实例在不同的 CPU 内核上运行?有没有办法跟踪哪一个,也许还有一些零星的打印语句?
问题 4 [新问题]
社区讨论提出了一个新问题。生成新进程时(在新的 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,))
第二种方法有一个明显的缺点,它只针对一个函数——而我需要打开一个新的 Python 脚本。无论如何,这两种方法在实现的目标上是否相似?
最佳答案
Q: Is it true that a Python interpreter uses only one CPU core at a time to run all the threads?
没有。 GIL 和 CPU 亲和性是不相关的概念。 GIL 可以在阻塞 I/O 操作期间释放,无论如何在 C 扩展中进行长时间的 CPU 密集型计算。
如果一个线程在 GIL 上被阻塞;它可能不在任何 CPU 内核上,因此可以公平地说纯 Python 多线程代码在 CPython 实现中一次只能使用一个 CPU 内核。
Q: In other words, will the Python interpreter session 1 (from the figure) run all 3 threads (Main_thread, TCP_thread and UDP_thread) on one CPU core?
我认为 CPython 不会隐式管理 CPU 关联性。它可能依赖于操作系统调度程序来选择在哪里运行线程。 Python 线程是在真正的 OS 线程之上实现的。
Q: Or is the Python interpreter able to spread them over multiple cores?
要找出可用 CPU 的数量:
>>> import os
>>> len(os.sched_getaffinity(0))
16
同样,线程是否调度在不同的 CPU 上并不依赖于 Python 解释器。
Q: Suppose that the answer to Question 1 is 'multiple cores', do I have a way to track on which core each thread is running, perhaps with some sporadic print statements? If the answer to Question 1 is 'only one core', do I have a way to track which one it is?
我想,一个特定的 CPU 可能会从一个时隙更改为另一个时隙。你可以 look at something like /proc/<pid>/task/<tid>/status
on old Linux kernels .在我的机器上, task_cpu
can be read from /proc/<pid>/stat
or /proc/<pid>/task/<tid>/stat
:
>>> open("/proc/{pid}/stat".format(pid=os.getpid()), 'rb').read().split()[-14]
'4'
对于当前的可移植解决方案,请查看 psutil
公开此类信息。
您可以将当前进程限制为一组 CPU:
os.sched_setaffinity(0, {0}) # current process on 0-th core
Q: For this question we forget about threads, but we focus on the subprocess mechanism in Python. Starting a new subprocess implies starting up a new Python interpreter session/shell. Is this correct?
是的。 subprocess
模块创建新的操作系统进程。如果你运行 python
可执行文件,然后它会启动一个新的 Python 解释器。如果您运行 bash 脚本,则不会创建新的 Python 解释器,即运行 bash
可执行文件不会启动新的 Python 解释器/ session /等。
Q: Supposing that it is correct, will Python be smart enough to make that separate interpreter session run on a different CPU core? Is there a way to track this, perhaps with some sporadic print statements as well?
见上文(即,操作系统决定在哪里运行您的线程,并且可能有操作系统 API 公开线程的运行位置)。
multiprocessing.Process(target=foo, args=(q,)).start()
multiprocessing.Process
还会创建一个新的操作系统进程(运行新的 Python 解释器)。
In reality, my subprocess is another file. So this example won't work for me.
Python 使用模块来组织代码。如果您的代码在 another_file.py
然后 import another_file
在您的主模块中并通过 another_file.foo
至multiprocessing.Process
.
Nevertheless, how would you compare it to p = subprocess.Popen(..)? Does it matter if I start the new process (or should I say 'python interpreter instance') with subprocess.Popen(..)versus multiprocessing.Process(..)?
multiprocessing.Process()
可能在 subprocess.Popen()
之上实现. multiprocessing
提供类似于 threading
的 API API 并抽象出 Python 进程之间的通信细节(Python 对象如何序列化以在进程之间发送)。
如果没有 CPU 密集型任务,那么您可以在单个进程中运行您的 GUI 和 I/O 线程。如果您有一系列 CPU 密集型任务,那么要一次使用多个 CPU,请使用具有 C 扩展名的多个线程,例如 lxml
, regex
, numpy
(或您自己使用 Cython 创建的)可以在长时间计算期间释放 GIL 或将它们卸载到单独的进程中(一种简单的方法是使用由 concurrent.futures
提供的进程池)。
Q: The community discussion raised a new question. There are apparently two approaches when spawning a new process (within a new Python interpreter instance):
# 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,))
“方法 1(a)” 在 POSIX 上是错误的(尽管它可能在 Windows 上工作)。为了便于携带,请使用“方法 1(b)”,除非您知道自己需要 cmd.exe
(在这种情况下传递一个字符串,以确保使用正确的命令行转义)。
The second approach has the obvious downside that it targets just a function - whereas I need to open up a new Python script. Anyway, are both approaches similar in what they achieve?
subprocess
创建新进程,any 进程,例如,您可以运行 bash 脚本。 multprocessing
用于在另一个进程中运行 Python 代码。 导入 Python 模块并运行其功能比将其作为脚本运行更灵活。见 Call python script with input with in a python script using subprocess .
关于python - 我的 Python 进程在哪些 CPU 内核上运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36795086/
我是 Linux 的新手,并且继承了保持我们的单一 Linux 服务器运行的职责。这是我们的SVN服务器,所以比较重要。 原来在我之前维护它的人有一个 cron 任务,当有太多 svnserve 进程
Node 虽然自身存在多个线程,但是运行在 v8 上的 JavaScript 是单线程的。Node 的 child_process 模块用于创建子进程,我们可以通过子进程充分利用 CPU。范例:
Jenkins 有这么多进程处于事件状态是否正常? 我检查了我的设置,我只配置了 2 个“执行者”... htop http://d.pr/i/RZzG+ 最佳答案 您不仅要限制 Master 中的执
我正在尝试在 scala 中运行这样的 bash 命令: cat "example file.txt" | grep abc Scala 有一个特殊的流程管道语法,所以这是我的第一个方法: val f
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我需要一些帮助来理解并发编程的基础知识。事实上,我读得越多,就越感到困惑。因此,我理解进程是顺序执行的程序的一个实例,并且它可以由一个或多个线程组成。在单核CPU中,一次只能执行一个线程,而在多核CP
我的问题是在上一次集成测试后服务器进程没有关闭。 在integration.rs中,我有: lazy_static! { static ref SERVER: Arc> = {
我正在使用 Scala scala.sys.process图书馆。 我知道我可以用 ! 捕获退出代码和输出 !!但是如果我想同时捕获两者呢? 我看过这个答案 https://stackoverflow
我正在开发一个C++类(MyClass.cpp),将其编译为动态共享库(MyClass.so)。 同一台Linux计算机上运行的两个不同应用程序将使用此共享库。 它们是两个不同的应用程序。它不是多线程
我在我的 C 程序中使用 recvfrom() 从多个客户端接收 UDP 数据包,这些客户端可以使用自定义用户名登录。一旦他们登录,我希望他们的用户名与唯一的客户端进程配对,这样服务器就可以通过数据包
如何更改程序,以便函数 function_delayed_1 和 function_delayed_2 仅同时执行一次: int main(int argc, char *argv[]) {
考虑这两个程序: //in #define MAX 50 int main(int argc, char* argv[]) { int *count; int fd=shm
请告诉我如何一次打开三个终端,这样我的项目就可以轻松执行,而不必打开三个终端三次然后运行三个exe文件。请问我们如何通过脚本来做到这一点,即打开三个终端并执行三个 exe 文件。 最佳答案 在后台运行
我编写了一个监控服务来跟踪一组进程,并在服务行为异常、内存使用率高、超出 CPU 运行时间等时发出通知。 这在我的本地计算机上运行良好,但我需要它指向远程机器并获取这些机器上的进程信息。 我的方法,在
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 8年前关闭。 Improve this qu
我有一个允许用户上传文件的应用程序。上传完成后,必须在服务器上完成许多处理步骤(解压、存储、验证等...),因此稍后会在一切完成后通过电子邮件通知用户。 我见过很多示例,其中 System.Compo
这个问题对很多人来说可能听起来很愚蠢,但我想对这个话题有一个清晰的理解。例如:当我们在 linux(ubuntu, x86) 上构建一个 C 程序时,它会在成功编译和链接过程后生成 a.out。 a.
ps -eaf | grep java 命令在这里不是识别进程是否是 java 进程的解决方案,因为执行此命令后我的许多 java 进程未在输出中列出。 最佳答案 简答(希望有人写一个更全面的): 获
我有几个与内核态和用户态的 Windows 进程相关的问题。 如果我有一个 hello world 应用程序和一个暴露新系统调用 foo() 的 hello world 驱动程序,我很好奇在内核模式下
我找不到很多关于 Windows 中不受信任的完整性级别的信息,对此有一些疑问: 是否有不受信任的完整性级别进程可以创建命名对象的地方? (互斥锁、事件等) 不受信任的完整性级别进程是否应该能够打开一
我是一名优秀的程序员,十分优秀!