【问题标题】:Python multiprocessing copy-on-write behaving differently between OSX and UbuntuPython 多处理写入时复制在 OSX 和 Ubuntu 之间的行为不同
【发布时间】:2019-05-19 09:02:43
【问题描述】:

我正在尝试在 Python 中的父进程和子进程之间共享对象。为了实现这个想法,我创建了一个简单的 Python 脚本:

from multiprocessing import Process
from os import getpid

import psutil

shared = list(range(20000000))

def shared_printer():
    mem = psutil.Process(getpid()).memory_info().rss / (1024 ** 2)
    print(getpid(), len(shared), '{}MB'.format(mem))

if __name__ == '__main__':
    p = Process(target=shared_printer)
    p.start()
    shared_printer()
    p.join()

代码 sn-p 使用优秀的psutil 库来打印 RSS(驻留集大小)。当我使用 Python 2.7.15 在 OSX 上运行它时,我得到以下输出:

(33101, 20000000, '1MB')
(33100, 20000000, '626MB')

当我在 Ubuntu(Linux 4.15.0-1029-aws #30-Ubuntu SMP x86_64 GNU/Linux)上运行完全相同的 sn-p 时,我得到以下输出:

(4077, 20000000, '632MB')
(4078, 20000000, '629MB')

请注意,子进程的 RSS 在 OSX 上基本为 0MB,与父进程在 Linux 中的 RSS 大小大致相同。我曾假设写时复制行为在 Linux 中以相同的方式工作,并允许子进程引用父进程的大多数页面的内存(可能除了存储对象头部的那个)。

所以我猜这两个系统的写时复制行为存在一些差异。我的问题是:我可以在 Linux 中做些什么来获得类似 OSX 的写时复制行为吗?

【问题讨论】:

  • 查看该问题的最佳答案stackoverflow.com/questions/1268252/…
  • 可能只是操作系统如何报告 RSS 值的问题?除了查看进程的内存外,还要检查 fork 之前/之后的空闲内存,看看 600MB 是否消失。
  • 您所有的库可能都在 CPython for MAC 中静态链接,而不是在 Ubuntu 上?看superuser.com/questions/1162037/…
  • @ShadowRanger 我的第一个想法也是关于 GC,但无论如何行为都是一致的。我认为这与 XNU 系统报告内存的方式有关。请参阅host_statistics 上的this question(由psutil 使用)以及为什么其结果跨平台不一致的答案。

标签: python linux shared-memory python-multiprocessing copy-on-write


【解决方案1】:

所以我猜这两个系统的写时复制行为存在一些差异。我的问题是:我可以在 Linux 中做些什么来>获得类似于 OSX 的写时复制行为吗?

答案是。在命令psutil.Process(getpid()).memory_info().rss / (1024 ** 2) 后面,操作系统使用UNIX 命令$top [PID] 并搜索字段RES。其中包含任务在 kb 中使用的非交换物理内存。即 RES = 代码 + 数据。

恕我直言,这意味着两个操作系统都使用不同的内存管理器。因此,几乎不可能限制一个进程使用/需要多少内存。这是操作系统的实习生问题。 在 Linux 中,子进程的大小与父进程相同。事实上,它们复制了相同的堆栈、代码和数据。但不同的PCB(过程控制块)。因此,不可能像 OSX 那样接近 0。闻起来,OSX 并没有从字面上复制代码和数据。如果它们是相同的代码,它将指向父进程的数据。

PD:希望对你有帮助!

【讨论】:

  • Linux 和 OSX 都应该使用 fork 和相同的写时复制语义,用于子代从父代分叉时存在的内存。我更倾向于怀疑 OSX counts 内存的方式不同,而不是它使用了多少内存。在 fork 之后,它们都应该几乎没有真正的内存使用,但是 Linux 可能会报告内存使用情况,假设所有写时复制页面最终都被复制(感谢 CPython 的引用计数+循环收集器设计,很可能会),而 OSX 只报告唯一的私有、非写时复制页面。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 2016-08-26
  • 2017-09-28
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多