为何multiprocessing.Queue.put()序列化numpy数组比pickle更快?
你的猜测完全正确——multiprocessing.Queue.put() 并不会等待对象完成序列化就返回,序列化操作是异步在后台线程执行的。
核心原因拆解
multiprocessing.Queue 的异步序列化机制
当你调用multiprocessing.Queue.put()时,它只是把待传递的对象交给一个后台守护线程,然后立即返回给主线程。真正的对象序列化(类似pickle.dumps的逻辑)、跨进程管道传输等耗时操作,都由这个后台线程在后台异步完成。这就是单独调用put1000次耗时不足2.5ms的原因——主线程只是完成了任务提交,没有等待实际的序列化工作结束。put+get 的同步阻塞效应
当你在f()里连续调用put()和get()时,get()必须等待对应的对象完成序列化、通过管道传输到接收端,并且完成反序列化后才能返回结果。这相当于把原本异步的序列化/传输操作强制变成了同步阻塞流程,每一次put后都要等整个序列化-传输-反序列化链路完成才能继续,总耗时自然剧增(甚至比单纯pickle.dumps更久,因为额外包含了反序列化和管道传输的开销)。
补充:如果是线程队列 queue.Queue?
如果你使用的是标准库 queue.Queue(线程安全队列),那它根本不需要序列化——因为线程共享同一地址空间,put() 只是把对象的引用存入队列,get() 直接取出引用,所有操作都会极快,不会出现你测试中 f() 耗时42秒的情况。结合你的测试数据,你实际使用的应该是 multiprocessing.Queue。
对应你的测试数据
- 单独
q.put(a)1000次:仅提交任务到后台,主线程无阻塞,耗时0.0025ms。 - 单独
pickle.dumps(a)1000次:同步序列化大数组,耗时2.6秒。 put+get1000次:强制同步等待序列化+传输+反序列化,总耗时42秒。
内容的提问来源于stack exchange,提问作者chaimp

