【问题标题】:Find minimum queue size among threads在线程中查找最小队列大小
【发布时间】:2013-01-08 13:25:36
【问题描述】:

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

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

我正在开发 Visual Studio 2008,我们自己的多线程库中的 C++ 编程语言实现了多速率同步数据流范例。

【问题讨论】:

  • 您是否有理由不能在所有线程中使用 single 队列?这样就不会出现平衡队列大小的问题。
  • @NPE:有多个队列,你可以用单写/读模式有效地实现它们。
  • @NPEyes 使用线程本地队列将有效地实现具有单个写入器/读取器模式的每个线程

标签: c++ multithreading scheduling task-queue


【解决方案1】:

正如您所见,试图找到负载较少的队列很麻烦,并且可能是一种效率低下的方法,因为您可能会向只有一项繁重任务的队列添加更多工作,而具有小任务的队列将没有更多工作并且很快就会变得不活动。

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

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

您不应该遇到空闲线程和工作等待处理的情况。

【讨论】:

  • +1,这更好,但用无锁队列实现更复杂 - 队列有多个消费者。我知道存在工作窃取池,只是不确定它们在内部是如何工作的。
【解决方案2】:

如果你真的想试试这个,每个队列是否可以不只保留一个公共的“int count”成员,在推送/弹出任务时使用原子 inc/dec 更新?

这样的设计是否值得管理开销以及当任务排队到恰好正在运行特别冗长的作业的线程时,当另一个线程即将出列一个非常短的作业时偶尔出现的“错误”,是另一个问题。

【讨论】:

  • 这就像为每个队列创建一个私有 int 计数,在推送任务时增加其计数,在弹出时减少其计数,然后将任务分派到看到此计数的队列。跨度>
  • 是 - 迭代队列并将任务分派到计数最低(或找到的第一个零)的队列。
  • 正如你所说,不是完全同步,但可能是最简单和最高效的解决方案。
  • @MartinJames:是的,您所说的另一个问题将是一个问题,因为我们不知道每个任务的确切执行时间。但我认为通常线程执行的任务的处理时间有点等价?是真的吗?
  • @rahul,我不知道 - 它们是你的任务,你应该知道 :)
【解决方案3】:

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

如果您真的想将工作项从主源分发到一组工作人员,那么您就是在进行负载平衡,正如您所说。在这种情况下,您实际上是在谈论调度,除非您只是简单地进行循环式平衡。调度是计算中非常深入的主题,您可以轻松地花费数周或数月的时间来学习它。

【讨论】:

  • 我猜测 OP 想要使用无锁队列,并希望消除锁开销将超过队列迭代开销以及导致作业的错误排队决策的可能性当另一个线程空闲时,卡在一个繁忙线程的队列上。我不相信这是一个好的设计,但我没有尝试过类似的东西,所以不确定。
【解决方案4】:

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

既然你想用数据流来实现一切,那么一切都应该是队列。

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

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

【讨论】:

  • 在您的第二个选项中,您说“您还有 n 个队列,每个队列从一个工作线程到调度程序线程”。我不清楚。你能解释清楚一点吗
  • @rahul:目前每个线程都有一个队列,对吧?您可以为每个线程添加另一个队列,因此每个线程有两个队列。一个用于向线程发送作业,另一个方向用于告诉调度程序线程从队列中消耗了一个作业。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-05
  • 2010-11-24
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2020-01-29
相关资源
最近更新 更多