2013-01-08 35 views
0

我正尝试使用多线程实现新的调度技术。每个线程都有自己的专用本地队列。这个想法是,每次从程序线程创建任务时,它应该搜索队列中的最小队列大小(任务数较少的队列)并排入其中。 线程之间的负载平衡方式,其中较少繁忙的队列排队更多。查找线程中的最小队列大小

能否请您建议一些逻辑(或)想法如何在编程的角度动态地在给定队列中找到最小大小的队列。

我正在使用visual studio 2008,C++编程语言在我们自己的多线程库中实现多速率同步数据流范例。

+0

是否有理由不能在所有线程中使用* single *队列?那么平衡队列大小的问题就不会出现。 – NPE

+0

@NPE:拥有多个队列,您可以使用单个写入器/阅读器模式高效地实现它们。使用线程本地队列将有效地实现单写入/读取器模式 – duedl0r

+0

@NPEyes和当另一个线程变为空闲时,可能会发生错误的排队决策,导致作业在队列中停留在繁忙的线程中。我不相信这是一个很好的设计,但我没有尝试过任何类似的东西,所以不确定。 – aram

回答

0

如果你真的想试试这个,每个队列不能只保留一个公共的'int count'成员,当任务被压入/弹出时用atomic inc/dec进行更新?

无论这样的设计是否值得管理开销,以及当任务排队等待恰好运行特别冗长的工作的线程时,另一个线程正准备离队一个非常短的工作时,偶尔会出现“错误”另一个问题。

+0

这就像为每个队列创建一个私有int计数,在任务被推入时增加它的计数,在弹出时减少它的计数,并且任务被分派到队列中看到这个计数。 – aram

+0

是 - 迭代队列并将任务分派到最低(或找到第一个零)的队列中。 –

+0

正如您所说,并非完全同步,但可能是最简单和最高效的解决方案。 – duedl0r

0

为什么线程不从“主”工作队列中获取工作?

如果您确实想要将工作项目从主源派发到一组工作者,那么您就可以像您说的那样进行负载平衡。在那种情况下,你真的在​​谈论调度,除非你简单地进行循环式的平衡。计划是计算中非常深刻的主题,您可以轻松地花费数周或数月时间来了解计算。

+1

我猜的OP要使用无锁队列和希望,锁开销的消除将开销大于队列迭代每个线程 –

0

您可以在线程中同步计数器。但我想这不是你想要的。

由于您想要使用数据流来实现所有功能,所有内容都应该是队列。

您的第一个选择是查询队列中的作业数量。我认为这并不容易,如果你想要一个单一的读写器模式,因为你可能不得不使用锁来进行这个操作,这不是你想要的。注意:我只是猜测,你不能在这里使用无锁队列;要么有计数器,要么取两个指针的差值,无论哪种方式你都有锁。

第二个选项(可以使用无锁代码完成)是将命令发送回调度程序线程,告诉他工作线程x已经完成了一项任务。使用这种方法,您有更多的队列,每个队列都从一个工作线程到调度程序线程。

+0

你的第二个选项,你说'你有更多的队列,每个从一个工作线程到调度线程'。我不清楚它。能否请你解释清楚一点 – aram

+0

@rahul:目前你每个线程有一个队列,对吧?您可以为每个线程添加另一个队列,以便每个线程有两个队列。一个用于向线程发送作业,另一个用于告知调度程序线程从队列中消耗一个作业。 – duedl0r

1

正如你所看到的,试图找到加载较少的队列很麻烦,而且可能是一种效率低下的方法,因为只需要一项繁重的任务就可以将更多工作添加到队列中,而具有小型任务的队列将不会有更多的工作并快速失效。

你最好使用工作窃取启发式:当一个线程完成它自己的工作时,它会查看其他线程队列并“窃取”一些工作,而不是保持空闲或被终止。

然后系统将自动平衡,每个线程都处于活动状态,直到没有足够的工作给每个人。

你不应该有空闲的线程和工作等待处理的情况。

+0

+1,这是更好的,但更复杂的实现与无锁队列 - 队列有多个消费者。我知道存在盗窃工作池,但不知道他们是如何在内部工作的。 –