线程管理建议 - TPL是个好主意吗?

时间:2010-04-26 12:02:07

标签: c# parallel-processing heuristics

我希望得到一些关于线程管理的使用的建议,并希望任务并行库,因为我不确定我是否已经走正确的路线。可能最好的是我概述了我要做的事情。

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

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

  1. 他们需要使用不同的“优化指标”进行初始化。换句话说,他们试图优化不同的东西,在代码中设置优先级。这意味着它们都运行略有不同的计算引擎。我不确定我是否可以用TPL来做这件事。
  2. 如果其中一个线程找到了当前最知名的解决方案(需要在所有线程之间共享)的更好解决方案,那么它需要更新最佳解决方案,并强制重启其他一些线程(这又取决于关于优化指标的优先级)。
  3. 我可能还希望跨线程组合某些计算(例如,保持某种方法解决问题的概率联合)。这可能是更加可选的。
  4. 整个系统显然需要线程安全,我希望它尽可能快地运行。
  5. 我尝试了一个涉及管理我自己的线程并关闭它们的实现,但它开始变得非常复杂,我现在想知道TPL是否会更好。我想知道是否有人可以提供任何一般指导?

    ...谢谢

2 个答案:

答案 0 :(得分:4)

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

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

  

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

您可以通过创建任务并向其传递不同的起始条件来实现此目的。

  

2.如果其中一个线程找到了目前最为人所知的更好的解决方案   解决方案(需要共享   所有线程)然后它需要   更新最佳解决方案,并强制a   要重启的其他线程数   (这又取决于优先顺序   优化指标的水平。)

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

  

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

不确定我理解这个要求。

  

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

即使TPL是您在任务(线程)之间共享数据,那么您仍然有责任以线程安全的方式执行此操作。但是,TPL附带了几个线程安全类,用于队列,集合,包等。

从它的声音来看,这是主/工作模式的一个变体,带有一些推测性的执行和工作窃取。你可以在http://parallelpatterns.codeplex.com/找到关于这个和其他模式的更多细节。由Stephen Toub撰写的白皮书页面也涵盖了其他细节。

答案 1 :(得分:0)

无论你怎么做,这都会很复杂。编写适当的同步代码非常困难。而且我认为TPL对此有点过分了。

我的建议是坐下来看看问题并将其白板化,尽量消除尽可能多的复杂性。

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

抵制启动3,000个线程的诱惑,并注意竞争条件,如下所示:拉开共享课程的读卡器锁定,检查你的答案 - 让我们说这是一个更好的答案,放下读卡器锁定并拉动writer锁定并更新共享类。这里的问题是,在你等待写入程序锁定的时候,另一个线程可能已经更新了类,你只需要在没有写入锁定的情况下将其删除,而不会检查它。

玩得开心。