5

我希望就线程管理的使用以及任务并行库的使用获得一些建议,因为我不确定我是否走在正确的道路上。最好的可能是我概述了我正在尝试做的事情。

给定一个问题,我需要使用基于启发式的算法生成解决方案。我从计算一个基本解决方案开始,我认为这个操作不能并行化,所以我们不需要担心。

生成初始解决方案后,我想触发n 个线程,试图找到更好的解决方案。这些线程需要做几件事:

  1. 它们需要使用不同的“优化指标”进行初始化。换句话说,他们试图优化不同的东西,在代码中设置优先级。这意味着它们都运行略有不同的计算引擎。我不确定我是否可以用 TPL 做到这一点。
  2. 如果其中一个线程找到了比当前最知名的解决方案更好的解决方案(需要在所有线程之间共享),那么它需要更新最佳解决方案,并强制许多其他线程重新启动(这同样取决于优先级的优化指标)。
  3. 我可能还希望跨线程组合某些计算(例如,为某种解决问题的方法保留概率的联合)。不过,这可能更可选。
  4. 整个系统显然需要是线程安全的,我希望它尽可能快地运行。

我尝试了一个涉及管理我自己的线程并关闭它们等的实现,但它开始变得相当复杂,我现在想知道 TPL 是否会更好。我想知道是否有人可以提供任何一般性指导?

谢谢...

4

2 回答 2

4

我肯定会看看TPL。它允许你抽象你的问题。您可以考虑任务以及它们如何工作和共享数据,而不是花费大量时间在底层线程模型上并创建您自己的线程并管理它们。TPL 将允许您创建分配给线程池的任务。然后 TPL 管理池并将调整运行任务的数量以最大限度地提高性能。它将在各种硬件配置(内核)上执行此操作,这使得开发和应用程序更容易,在不同硬件之间移动时不需要进行重大重写。

您仍然需要考虑很多事情,尤其是在共享状态方面。TPL 通常是比自己滚动更好的方法,除非您对线程非常有经验和/或有一些 TPL 不适合的特殊情况应用程序。

1.他们需要用不同的“优化指标”来初始化。换句话说,他们试图优化不同的东西,在代码中设置优先级。这意味着它们都运行略有不同的计算引擎。我不确定我是否可以用 TPL 做到这一点。

您可以通过创建任务并为它们传递不同的起始条件来做到这一点。

2.如果其中一个线程找到了比当前最知名的解决方案更好的解决方案(需要在所有线程之间共享),那么它需要更新最佳解决方案,并强制许多其他线程重新启动(这又取决于优化指标的优先级)。

可以取消任务并启动新任务。

3.我可能还希望跨线程组合某些计算(例如,为某种解决问题的方法保留概率的联合)。不过,这可能更可选。

不确定我是否理解这个要求。

4.整个系统显然需要是线程安全的,我希望它尽可能快地运行。

即使使用 TPL 是您跨任务(线程)共享数据,那么这仍然是您以线程安全的方式执行此操作的责任。然而,TPL 为队列、集合、包等提供了几个线程安全类。

从它的声音来看,这是主/工作者模式的一种变体,其中包含一些推测性执行和工作窃取。您可以在http://parallelpatterns.codeplex.com/找到有关此模式和其他模式的更多详细信息。页面底部到 Stephen Toub 的白皮书,其中也包含更多细节。

于 2010-04-26T20:16:03.697 回答
0

不管你怎么做,这都会很复杂。编写正确的同步代码非常困难。而且我认为 TPL 将为此过分。

我的建议是坐下来看看问题,然后把它写下来,尽量消除复杂性。

也许这会有所帮助...创建一个优化指标队列和一个具有最佳答案的共享类。用读写器锁保护你的共享类,用互斥锁或其他锁保护你的队列。启动 4-8 个线程(每个 CPU 一个线程,如果阻塞很多,则更多)并让它们循环运行。从队列中删除一个项目,处理它,检查共享数据,重复直到没有更多项目。

抵制启动 3,000 个线程并注意竞争条件的诱惑,例如:在共享类上拉读锁,检查你的答案 - 假设这是一个更好的答案,放下读锁并拉写锁并更新共享类。这里的问题是,另一个线程可能在您等待编写器锁定时更新了该类,而一旦您拥有编写器锁定,您就吹走了“最佳”答案而没有检查它。

玩得开心。

于 2010-04-26T15:25:11.697 回答