代码之家  ›  专栏  ›  技术社区  ›  Ian

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

  •  5
  • Ian  · 技术社区  · 16 年前

    我希望得到一些关于线程管理使用的建议,并希望得到任务并行库,因为我不确定我走的是正确的路线。也许最好的办法是我给出一个我想做什么的大纲。

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

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

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

    我尝试了相当多的实现,包括管理自己的线程和关闭它们等等,但是它开始变得相当复杂,我现在想知道TPL是否更好。我想知道是否有人能提供一般性的指导?

    谢谢。。。

    2 回复  |  直到 16 年前
        1
  •  4
  •   Ade Miller    16 年前

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

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

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

    您可以通过创建任务并传递不同的开始条件来实现这一点。

    2.如果其中一个线程找到一个更好的解决方案 解决方案(需要共享 然后它需要 更新最佳解决方案并强制 要重新启动的其他线程数 (同样,这取决于优先级 优化指标的级别)。

    可以取消任务并开始新任务。

    3.我可能还希望结合线程之间的某些计算(例如, 概率的联合 解决问题)。这是 但可能更为可选。

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

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

    即使有了TPL,您也可以跨任务(线程)共享数据,那么您仍然有责任以线程安全的方式来实现这一点。但是,TPL附带了几个用于排队、收集、打包等的线程安全类。

    从声音上看,这是主/工作模式的一个变体,带有一些推测性的执行和工作窃取。有关此模式和其他模式的详细信息,请访问 http://parallelpatterns.codeplex.com/ 页面底部有一个链接,指向斯蒂芬图布的白皮书,其中也包含了其他细节。

        2
  •  0
  •   Karl Strings    16 年前

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

    我的建议是坐下来,看看问题和白板它出来,并试图消除尽可能多的复杂性。

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

    抵制启动3000个线程的诱惑,并注意竞争条件,比如:在共享类上拉读卡器锁,检查您的答案——假设这是一个更好的答案,那么就删除读卡器锁,拉写器锁,然后更新共享类。这里的问题是,当您在等待编写器锁时,另一个线程可能已经更新了类,而您只是在拥有编写器锁时不检查它就吹走了“最佳”答案。

    玩得高兴。