多线程任务总体进度报告的设计模式

时间:2011-10-12 18:59:20

标签: c++ multithreading design-patterns

我有一个带有IJobMaker实体的库,它创建了一定数量的IJob个对象,这些对象将在用户管理的自己的线程上运行。 为了跟踪每个IJob的进度,我在每个作业中使用IProgressObserver实现观察者模式。当我希望报告总体进展时,就会出现困难。

我的理想选择是IProgressOverserver.ReportProgress(float jobProgress, float overallProgress报告工作和整体进度。IJobMaker可以了解每项工作的整体工作部分,并以某种方式收集每个人的报告。

出现两个主要问题:

  1. 同步机制?例如,在IJobMaker内部使用互斥锁可能会损害性能,因为IProgressOverserver.ReportProgress会被大量调用,而互斥锁可能会导致上下文切换,什么不会。 InterlockedIncrement看起来是一个不错的选择,但由于浮点没有这样的函数,我将被迫以整数增量报告进度。 (我想远离c ++ 0x功能或Boost)

  2. 设计模式? IJob的最新算法报告了IProgressObserver.ReportProgress的进展。我需要每个这样的报告都与中央实体进行通信以进行总体进度计算,并调用驻留在IJob中的{{1}}方法。

2 个答案:

答案 0 :(得分:1)

关于线程前端的一些建议:

  1. 不要报告最微小的进展。只有在已经进行了某个预定义的进度,或者已经过了某个预定义的时间量或者子作业已经完成时,才向主线程报告。这可以大大减少同步量。
  2. 如果实现#1,互斥锁可能会运行良好。
  3. 如果互斥体过于昂贵,您可以使用原子整数变量报告进度:只需将值从“无进度”缩放到“全部完成”到0 ... {{1} }。
  4. 就设计API而言,想出一些合理的东西应该不会太难。我的一般建议是不要过度工程化。

答案 1 :(得分:0)

首先,在这种情况下使用浮动是非常糟糕的做法。使用整数。

还有另一个建议。您可以使用分段 - 仅通过一个互斥/原子(一个段)同步少数线程。然后在所有细分中收集总数。

此外,还有一个好地方可以开始寻找高度并行的算法:http://www.1024cores.net/home/lock-free-algorithms

<强> UDPATE 浮动

存在问题的例子
#include <iostream>
using namespace std;
int main() {
    float f = 0;
    for(int i=0; i<100000-98; ++i)
    {
        f += 0.00001;
    }
    cout << f << endl;
}

所以,如果你有100个工作,每个工作1000个步骤,你将比你预期的更早得到1.0个结果。