【发布时间】: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