如何在C ++中同步和组合多个线程的结果?

时间:2009-11-04 16:12:00

标签: c++ multithreading boost synchronization performance

我有一个数据源连续输入数据包。有5个线程(A,B,C,D,E)处理数据包。请注意,5个线程的速度完全不同,它们为每个传入的数据包生成5个不同的功能(每个线程生成1个功能)。

5个线程处于不同的速度:当A完成对前10个包的分析时,B可能只完成了包1,包2,而C可能根本没有完成单个包。

我的任务是匹配5个线程的结果,并在前10个数据包的所有5个功能都可用时开始最终分析。

我的问题是:   - 如何组合来自不同线程的结果,确保仅在有一定数量的结果可用时才触发分析线程?   - 我似乎需要一个聚合器线程来检查不同缓冲区的可用性。我在考虑锁定/状况。我怎么能实现这种涉及不同缓冲区的条件?

多线程的新手。欢迎提出任何建议。

我正在使用GNU C ++和Boost库。

7 个答案:

答案 0 :(得分:3)

让自己有一个“聚合器”线程:这个线程将从工作线程获得它的输入(通过我建议的非阻塞线程安全队列),并且一旦“批处理”准备就绪,将其推送到“分析器”线程

队列提供​​了不阻止任何工作者的优势:“聚合器”只需轮询工作队列(通过条件部分)。您可以根据自己的喜好控制轮询率。

此解决方案解决了“同步所有”情况的问题。

答案 1 :(得分:1)

您可能需要查看Producer-consumer problem

答案 2 :(得分:1)

使用信号量和额外的布尔“完成”变量。每次完成一个线程,它首先写出它的答案,然后它的'完成'变量,然后调用一个'检查'函数,检查所有踏板'完成'变量,如果它们都是真的触发分析线程。

取决于你的性能权衡,你可能只想要最慢的'工作'线程来调用'check'函数,所以快速的线程不会保持锁定它的'done'变量来进行读取。当然,这取决于知道哪个是最慢的。

我不知道您的重置政策:您是想每次等待10个新输入还是最近连续分析10个?

答案 3 :(得分:1)

一些伪代码:

worker thread: 
   -> do work, 
     -> publish result to queue
   -> 10 reached, signal my condvar 

aggregator thread: 
   -> wait on all condvars. 
   -> lock all result queues, swap in new empty ones.  
   -> do aggregation processing. 

创建新队列的原因是您的聚合处理可能导致大量锁定,并且如果删除项目则会失效 - 如果您在工作线程上放置新队列,则需要更少担心锁定(尤其是聚合器不需要与工人分享它的结果。

答案 4 :(得分:0)

障碍是规范的“同步所有”操作。

然而,听起来你想在一个关键部分有一个“计数结果”变量,当一定量完成时,该变量会增加。然后,你想做一个“阻塞,直到变量等于x”。这可以通过对计数结果变量进行自旋锁来实现。

答案 5 :(得分:0)

有一个存储结果的容器和这样的函数(伪代码):

void storeResult(Result result) {
    Mutex m("ResultContainerMutex");

    container.push_back(result);
    if(container.size() > ANALYSIS_SIZE) {
        StartAnalysisThread(container.copy());
        container.clear();
    }
}

由于互斥锁只是保护添加到容器操作的速度相当快,所以不应该导致过多的序列化。

答案 6 :(得分:0)

根据您当前的设计,您受限于最慢的计算,其他线程将无法使用。

如果你想处理大量的数据包,我会改变这样的工作:

将数据包分发到N个相同的线程,该线程按顺序计算它们收到的数据包的结果。

每个线程将其结果包放入线程安全的fifo。

您的主线程会读取结果,如果需要,可以使用数据包编号重新排序