Python 多处理队列的高性能替换

Python 多处理队列的高性能替换,python,message-queue,zeromq,Python,Message Queue,Zeromq,我的分布式应用程序由许多生产者组成,生产者将任务推送到几个FIFO队列中,每个队列都有多个使用者。所有这些组件都位于单个节点上,因此不涉及网络 Python内置的多处理.Queue非常支持这种模式,但是当我扩展应用程序时,队列实现似乎是一个瓶颈。我没有发送大量数据,因此内存共享无法解决问题。我需要的是每秒10^4-10^5条小消息的快速保证传递。每条消息大约有100字节 我对快速分布式计算的世界还很陌生,我对如此之多的选项感到非常困惑。有拉比、雷迪斯、卡夫卡等 ZeroMQ是一种更集中、更紧凑的

我的分布式应用程序由许多生产者组成,生产者将任务推送到几个FIFO队列中,每个队列都有多个使用者。所有这些组件都位于单个节点上,因此不涉及网络

Python内置的
多处理.Queue
非常支持这种模式,但是当我扩展应用程序时,队列实现似乎是一个瓶颈。我没有发送大量数据,因此内存共享无法解决问题。我需要的是每秒10^4-10^5条小消息的快速保证传递。每条消息大约有100字节

我对快速分布式计算的世界还很陌生,我对如此之多的选项感到非常困惑。有拉比、雷迪斯、卡夫卡等

ZeroMQ是一种更集中、更紧凑的替代方案,它也有后续产品,如nanomsg和nng。此外,在没有代理的情况下,实现具有保证交付的多对多队列似乎很重要


如果有人能为我指出一种“标准”的方法,用一种更快的框架来做类似的事情,我将不胜感激。

我认为这在很大程度上取决于你对个人信息的重视程度

如果每一个都是至关重要的,你必须考虑在某些地方发生故障时会发生什么,那么像RabBMQ这样的框架可能是有用的。RabbitMQ有一个代理,可以将其配置为某种高可用性、高可靠性模式。通过正确的队列设置,RabbitMQ将一直监视消息,直到系统的某个部分使用它们为止

要做到这一切,RabbitMQ需要一个代理。这使得它相当慢。尽管曾经有人讨论过在ZeroMQ的底层协议(zmtp)之上重新实现RabbitMQ,并取消代理,而是在端点中实现所有功能

相比之下,ZeroMQ在保证在发生故障时,您的消息最终会到达预期目的地方面做得远远不够。如果进程死亡,或网络连接失败,则消息丢失的可能性很高。更新的版本可以设置为主动监视连接,这样,如果网络电缆断开或某个进程在某处终止,套接字另一端的端点可以非常快地获知这一情况。如果在ZMQ的actor框架之上实现了一个通信顺序流程框架(想想:消息确认等,这会使它变慢),那么最终您可以得到一个系统,通过该系统,端点可以确定消息已被传输到预期的目的地

由于没有经纪人,zmq的速度非常快。它在许多不同的传输中都是高效的,从
inproc
tcp
,所有这些传输都可以混合在一起。如果您不担心进程崩溃或网络连接失败,ZMQ可以保证立即发送消息


因此,决定什么在应用程序中是重要的,有助于选择要作为应用程序一部分使用的技术—RabbitMQ、ZeroMQ等。一旦确定了这一点,“如何获得所需的模式”的问题就简化为“该技术支持什么模式”。RabbitMQ是纯粹的发布/订阅(每种都有很多),而ZeroMQ有更多

在尝试了一些可用的实现和框架之后,我仍然找不到任何适合我的任务的东西。要么太慢,要么太重

为了解决这个问题,我的同事和我制定了以下计划:

更快的fifo是Python的
多处理.Queue
的替代品,速度明显更快。事实上,在我关心的配置中(许多生产者,很少消费者),它的速度快了30倍,因为它还支持消费者端的
get_many()
方法


它是无中断、轻量级的,支持任意多对多配置,使用pthread同步原语为Posix系统实现。

为了取代Python标准的多处理队列,我尝试了Redis服务器队列。这是不适合Redis的!Python是最好、最快的,可以接受任何类型的数据类型,其中使用Redis和复杂的数据类型,例如使用大量numpy数组的dict等。。。您必须pickle或json转储/加载,这会增加流程的开销

干杯,
Steve

10^5条消息/秒在一个队列上是一个苛刻的要求:系统只有10微秒的时间来完全处理一条消息并为下一条消息做好准备。正如您的问题所提到的,您最好关注分布式计算,以便在多个节点之间共享负载,并通过添加节点实现可伸缩性。但这假设您的设计不会设置一个将成为瓶颈的队列……嗨,Aleksei,我已经尝试使用更快的fifo来取代pytorch多处理队列。它似乎不起作用。你知道我将如何调试它吗?@Paul,更快的fifo不是pytorch队列类的替代品,它只是标准python的multiprocessing.Queue的替代品。但据我所知,唯一的区别在于物体的酸洗。Torch为张量对象定义了自己的pickler。我相信你可以使用他们的pickler,它具有更快的fifo,只需很少的修改。我已经改为多处理队列,而不是torch.multiprocessing,并且应用程序仍然可以正常工作。File“/usr/lib/python3.6/multiprocessing/popen\u spawn\u posix.py”,第47行,在_launchreduction.dump(process\u obj,fp)文件中“/usr/lib/python3.6/multiprocessing/reduce.py”,dump-ForkingPickler(文件,协议)中的第60行。dump(obj)_-pickle.pickling错误:无法pickle:main上的属性查找c_-ubyte_-Array_2失败`Hi@user9784065!此队列不应死锁。生产者