首页 > 解决方案 > Python 上下文中的运行时是什么?它由什么组成?

问题描述

在这个问题的上下文中,什么是“运行时”?(https://stackoverflow.com/questions/3900549/what-is-runtime/3900561)

我试图了解 python 运行时是由什么组成的。我的猜测是:

  1. 包含所有运行时变量的 python 进程。
  2. 吉尔
  3. 底层解释器代码(CPython 等)。

现在,如果这是正确的,我们是否可以说 python 中的多处理创建了多个运行时,而 python 进程是我们可以直接与运行时相关的东西?(我认为这是正确的选择)

或者,每个具有自己的堆栈的 python 线程都可以在与父进程相同的 GIL 和内存空间上工作,都可以称为具有单独的运行时?

或者,不管有多少线程或进程正在运行,它们都将在一个运行时下运行?

简单来说,在 Python 的上下文中,runtime 的定义是什么?

PS:我理解线程和进程之间的区别。GIL:我理解影响,但我不理解它。

标签: pythonmultiprocessingruntimeterminologygil

解决方案


您正在谈论计算机科学中两个不同(但相似)的概念;多进程和多线程。以下是一些可能有用的问题/答案的汇编:

多处理是在单个计算机系统中使用两个或多个中央处理单元 (CPU)。该术语还指系统支持多个处理器的能力或在它们之间分配任务的能力。

在计算机体系结构中,多线程是中央处理单元 (CPU)(或多核处理器中的单核)在操作系统支持下同时提供多个执行线程的能力。这种方法不同于多处理。在多线程应用程序中,线程共享单个或多个内核的资源,包括计算单元、CPU 缓存和转换后备缓冲区 (TLB)。

过程

每个进程都提供执行程序所需的资源。进程具有虚拟地址空间、可执行代码、系统对象的打开句柄、安全上下文、唯一进程标识符、环境变量、优先级类别、最小和最大工作集大小以及至少一个执行线程。每个进程都从一个线程开始,通常称为主线程,但可以从它的任何线程创建额外的线程。

线

线程是进程中可以调度执行的实体。一个进程的所有线程共享它的虚拟地址空间和系统资源。此外,每个线程都维护异常处理程序、调度优先级、线程本地存储、唯一线程标识符以及系统将用于保存线程上下文直到被调度的一组结构。线程上下文包括线程的机器寄存器集、内核堆栈、线程环境块和线程进程地址空间中的用户堆栈。线程也可以有自己的安全上下文,可用于模拟客户端。


运行时环境基本上是在机器之上运行的虚拟机——提供机器抽象。它通常比图书馆低。框架可以包含运行时环境,但通常与库相关联。

在计算机编程中,运行时系统,也称为运行时环境,主要实现部分执行模型。大多数语言都有某种形式的运行时系统,它提供了程序运行的环境。该环境可以解决许多问题,包括应用程序内存的布局、程序如何访问变量、在过程之间传递参数的机制、与操作系统的接口等等。通常,运行时系统将负责设置和管理堆栈和堆,并且可能包括诸如垃圾收集、线程或语言中内置的其他动态特性等特性。

CPython 解释器用来确保一次只有一个线程执行 Python 字节码的机制。这通过使对象模型(包括关键的内置类型,如 dict)对并发访问隐式安全来简化 CPython 实现。锁定整个解释器使解释器更容易实现多线程,但代价是多处理器机器提供的大部分并行性。

然而,一些扩展模块,无论是标准的还是第三方的,都被设计成在执行压缩或散列等计算密集型任务时释放 GIL。此外,在执行 I/O 时总是释放 GIL。

过去创建“自由线程”解释器(以更精细的粒度锁定共享数据)的努力并未成功,因为在常见的单处理器情况下性能会受到影响。人们相信,克服这个性能问题将使实施更加复杂,因此维护成本更高。

有关 GIL 的更多信息的有用来源。

每当你 fork 时,整个 Python 进程都会在内存中复制(包括 Python 解释器、你的代码和任何库、当前堆栈等)以创建第二个进程——这是为什么 fork 进程比创建线程更昂贵的原因之一。

这将创建 python 解释器的新副本。

运行两个 python 解释器的一个优点是您现在有两个 GIL(全局解释器锁),因此可以在多核系统上进行真正的多处理。

一个进程中的线程共享相同的 GIL,这意味着在给定时刻只有一个线程运行,只给人一种并行的错觉。

Python 中的内存管理涉及一个包含所有 Python 对象和数据结构的私有堆。这个私有堆的管理由 Python 内存管理器在内部确保。Python 内存管理器具有处理各种动态存储管理方面的不同组件,例如共享、分段、预分配或缓存。


当您通过库生成线程时threading,您实际上是在单个 Python 运行时中生成作业。此运行时确保线程具有共享内存并通过以下方式管理这些线程的运行顺序global interpreter lock

当您通过multiprocessing库生成一个进程时,您将生成一个新进程,其中包含一个运行指定代码的新 Python 解释器(新运行时)。如果要共享内存,则必须使用multiprocessing.shared_memory

该模块提供了一个类,SharedMemory用于分配和管理要由多核或对称多处理器 (SMP) 机器上的一个或多个进程访问的共享内存。为了协助共享内存的生命周期管理,尤其是跨不同进程的共享内存,SharedMemoryManager在 multiprocessing.managers 模块中还提供了 BaseManager 子类。


我们可以说python中的多处理创建了多个运行时,而python进程是我们可以直接与运行时相关的东西吗?

是的。不同的 GIL,不同的内存空间,不同的运行时。

每个 Python 线程都有自己的堆栈,与父进程在相同的 GIL 和内存空间上工作,都可以称为具有单独的运行时吗?

取决于您所说的“堆栈”是什么意思。相同的 GIL、共享内存空间、相同的运行时。

不管有多少线程和进程正在运行,它们都将在一个运行时下运行?

取决于多线程/多进程。

简单来说,在 Python 的上下文中,runtime 的定义是什么?

运行时环境字面意思是python.exeor /usr/bin/python。它是 Python 可执行文件,它将通过将您的 Python 代码转换为 CPU 可读的字节码来解释它。当您使用多线程时,您只有一个python正在运行。当您运行multiprocess多个pythons 时。


我希望核心开发人员可以进来并更详细地谈论这个问题。目前,以上只是一个资源汇编,供您开始理解/看到更大的图景。


推荐阅读