我有一个看起来像这样的子系统:
[read] [decode] [deliver]
Byte --> Undecoded --> Decoded --> Output queue
stream message message
输入是套接字/字节流。第一步是阅读消息。下一步是解码消息(并将结果存储在消息对象中)。最后一步是传递信息。
我想并行化解码步骤,但我必须保持输出顺序与输入顺序相同。因此,如果收到消息A和B并且消息B的解码速度更快,我必须等到A完成传送它。
我在Java中做了一个天真的初始实现,但是我的分析表明我在切换步骤中丢失了太多(从“流读取器”到“解码器”以及从“解码器”到输出)。在24核计算机上运行测试程序(包括超线程)时,我得到:
我的天真实现可以在http://pastebin.com/be1JqZy3获得它超过200行代码,所以它可能只会让那些真正想知道如何使并行版本比串行速度慢10倍的人感兴趣(提示:开始看一下ThreadPoolDecoder类。
在执行此类问题时是否有任何人使用模式/框架,其中工作是继续的(基于流)可以并行化但必须在输出时进行排序?
答案 0 :(得分:2)
我在我编写的程序(在C#中)处理这个问题的方法是在输出上有一个优先级队列。每条记录都有一个相关的记录号,在读取时分配。这些数字从0开始增加。线程完成处理记录后,会将记录添加到优先级队列中。
单独的输出线程具有从零开始的预期记录编号。该线程监视队列,等待添加的预期记录号。添加预期记录后,线程将其从队列中删除,输出,增加其预期记录编号,然后再次尝试。
这在我的应用程序中运行良好,有四个线程处理记录和一个处理输出。
答案 1 :(得分:2)
1100 K msg / s非常快(消息不到1微秒)。此时间与从队列中放入/获取消息的时间(0.1 ... 1微秒)相当。因此,为了利用并行化,您必须将不间断处理的时间显着更多地保持在1微秒(例如,1毫秒)。如果您将小消息组合成较大的消息,则可以执行此操作。在数据包中累积1000条消息,并将数据包作为一个工作单元处理。并行处理单元。