【问题标题】:Is there a way to serialize/deserialize without engaging the python GIL有没有办法在不使用 python GIL 的情况下进行序列化/反序列化
【发布时间】:2019-11-13 20:57:15
【问题描述】:

快速测试表明 cPickle (python 3.6.9 import pickle defaults to using cPickle) 与 GIL 接合。

import pickle
import os

big_data = os.urandom(10000000)

def run():
    pickle.loads(pickle.dumps(big_data))

t = timeit.Timer(run)
[threading.Thread(target=lambda: t.timeit(number=2000)).start() for _ in range(4)]

运行序列化操作的 4 个线程的测试以 100% cpu 运行,例如它参与 GIL。运行 numpy 操作的相同类型的测试使用 400% cpu(没有 GIL 与 numpy 相关)。

我希望作为 C 函数的 cPickle 不会使用 GIL。有没有办法解决?我希望能够在不阻塞主进程的情况下反序列化大量数据。

我正在尝试将每秒 3GB 以上的数据从工作进程拉回主进程。我可以使用流式套接字和异步以 4GB/秒的速度移动数据,但反序列化是一个瓶颈。 I don't have the luxury of Python 3.8 和 SharedMemory 不幸的是。

一个可以接受的答案当然是肯定的。

【问题讨论】:

  • 我不明白为什么模块是 C 扩展的事实会让你认为它不会参与 GIL。据我了解,GIL 解决的基本问题是对 Python 解释器级别对象的线程安全访问,这些对象依赖于垃圾收集的引用计数。由于pickle 序列化/反序列化涉及其他线程可能访问的 Python 对象,因此它必须使用 GIL。
  • @juanpa.arrivillaga 如果您将其发布为答案,我会接受。你的解释听起来很可能是正确的。我将 C 函数等同于可以像 numpy 一样释放 GIL 的外部函数,但正如您指出的那样,在 Python 对象序列化的情况下这似乎不合理。

标签: python python-3.6 pickle python-multithreading


【解决方案1】:

从 cmets 那里得到@juanpa.arrivillaga 的回答来结束这个问题:

我不明白为什么模块是 C 扩展的事实会让您认为它不会参与 GIL。据我了解,GIL 解决的基本问题是对 Python 解释器级别对象的线程安全访问,这些对象依赖于垃圾收集的引用计数。由于 pickle 序列化/反序列化涉及其他线程可能有权访问的 Python 对象,因此它必须使用 GIL。

【讨论】:

    猜你喜欢
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多