我有一个数据源连续输入数据包。有5个线程(A,B,C,D,E)处理数据包。请注意,5个线程的速度完全不同,它们为每个传入的数据包生成5个不同的功能(每个线程生成1个功能)。
5个线程处于不同的速度:当A完成对前10个包的分析时,B可能只完成了包1,包2,而C可能根本没有完成单个包。
我的任务是匹配5个线程的结果,并在前10个数据包的所有5个功能都可用时开始最终分析。
我的问题是: - 如何组合来自不同线程的结果,确保仅在有一定数量的结果可用时才触发分析线程? - 我似乎需要一个聚合器线程来检查不同缓冲区的可用性。我在考虑锁定/状况。我怎么能实现这种涉及不同缓冲区的条件?
多线程的新手。欢迎提出任何建议。
我正在使用GNU C ++和Boost库。
答案 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。
您的主线程会读取结果,如果需要,可以使用数据包编号重新排序