繁体   English   中英

如何处理消息的并行处理?

[英]How to approach parallel processing of messages?

我正在为我的应用程序重新设计消息传递系统,以使用英特尔线程构建模块,并且为尝试在两种可能的方法之间做出决定而感到困惑。

基本上,我有一系列消息对象,对于每种消息类型,都有一系列处理程序。 对于每个消息对象,我将应用为该消息对象类型注册的每个处理程序。


顺序版本将如下所示(伪代码):

for each message in message_sequence                     <- SEQUENTIAL
    for each handler in (handler_table for message.type)
        apply handler to message                         <- SEQUENTIAL

我正在考虑的第一种方法依次(依次)处理消息对象并同时应用处理程序。

优点:

  • 消息的可预测顺序(即,我们保证有FIFO处理顺序)
  • (可能)降低处理每个消息的延迟

缺点:

  • 比单个消息类型的处理程序可用的处理资源更多(并行度差)
  • 错误使用处理器缓存,因为需要复制消息对象以供每个处理程序使用
  • 处理程序的大量开销

这种方法的伪代码如下:

for each message in message_sequence                              <- SEQUENTIAL
    parallel_for each handler in (handler_table for message.type)
        apply handler to message                                  <- PARALLEL

第二种方法是并行处理消息,然后将处理程序依次应用于每个消息。

优点:

  • 更好地使用处理器缓存(将消息对象保留在所有将使用它的处理程序中)
  • 小型处理程序不会带来太多开销(只要还有其他处理程序要运行)
  • 期望的消息多于处理程序,因此并行的可能性更大

缺点:

  • 不可预知的排序-如果消息A在消息B之前发送,则它们可能同时被处理,或者B可能在A的所有处理程序完成之前完成处理(顺序是不确定的)

伪代码如下:

parallel_for each message in message_sequence                     <- PARALLEL
    for each handler in (handler_table for message.type)
        apply handler to message                                  <- SEQUENTIAL

第二种方法比第一种具有更多的优点,但是不确定性排序是一个很大的缺点。

您会选择哪种方法,为什么? 我是否应该考虑其他方法(除了明显的第三种方法:并行消息和并行处理程序,它们都具有缺点,并且据我所知,没有真正的兑换因素)?

谢谢!

编辑:

我认为我将默认使用#2,但允许在每个消息上附加一个“会话标签”。 具有相同标签的任何消息都将根据其会话顺序进行排序和处理。 处理程序在消息旁边传递了会话标签,因此如果需要,他们可以继续进行会话。 像这样:

Conversation c = new_conversation()
send_message(a, c)
...
send_message(b, c)
...
send_message(x)

handler foo (msg, conv)
    send_message(z, c)

...
register_handler(foo, a.type)

a在b之前处理,b在z之前处理。 x可以与a,b和z并行处理。 处理完对话中的所有消息后,对话将被销毁。

我会说做些不同的事情。 不要工作发送到线程。 当线程完成以前的工作时,请拉动它们。

保持固定数量的工作线程(最佳数量等于系统中CPU内核的数量),并让每个工作线程在完成前一个任务后从全局队列中依次提取下一个任务。 显然,您需要跟踪消息之间的依赖性,以延迟对消息的处理,直到完全处理了其依赖性为止。

这可以通过非常小的同步开销来完成-可能仅通过原子操作即可,而无需使用互斥量或信号量之类的繁重基元。

另外,如果您通过引用将消息传递给每个处理程序,而不是进行复制,则由不同CPU内核上的不同处理程序同时处理同一条消息实际上可以提高缓存性能,因为更高级别的缓存(通常从L2起)通常在CPU内核之间共享 -因此,当一个处理程序将消息读入缓存时,第二个内核上的另一个处理程序将在L2中拥有此消息。 因此,请仔细考虑-您是否真的需要复制邮件?

我认为顺序是否重要很重要。 如果顺序不重要,则可以使用方法2。如果顺序很重要,则可以使用方法1。根据您的应用程序应该执行的操作,您仍然可以使用方法2,但是使用序列号,因此所有消息以正确的顺序进行处理(除非是您要优化的处理部分,除非有原因)。

如果可能的话,我会进行一些调整以争取第二名。 您真的需要按顺序发送每条消息吗? 我发现这是一个不寻常的情况。 我们只需要尽快处理一些消息,然后需要在其他消息之前处理某些消息,而不是在每条消息之前进行处理。

如果必须按顺序排列一些消息,请以某种方式标记它们。 您可以用一些对话代码标记它们,以使处理器知道必须相对于该对话中的其他消息按顺序进行处理。 然后,您可以同时处理所有无对话的消息和来自每个对话的一条消息。

给您的设计一个好的外观,并确保仅需要按顺序排列的消息。

第一种方法还具有不可预测的顺序。 在线程1上对消息1的处理可能会花费很长时间,这使得消息2、3和4可能已被长时间处理

这将使方法2的余额减少

编辑:我明白你的意思了。

但是,为什么要在方法2中按顺序执行处理程序。 在方法1中,顺序无关紧要,您可以。

例如方法3:并行处理消息和处理程序。

当然,这里的订购也不保证。

考虑到处理程序的某些结果,您可以将结果存储在一个有序列表中,从而最终恢复排序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM