C++ 并发::parallel_for(PPL)正在创建太多线程
我正在使用Visual Studio 2010的并行模式库(PPL)的C++ 并发::parallel_for(PPL)正在创建太多线程,c++,multithreading,concurrency,ppl,C++,Multithreading,Concurrency,Ppl,我正在使用Visual Studio 2010的并行模式库(PPL)的Concurrency::parallel_for()来处理一组索引任务(通常,索引集远远大于可以同时运行的线程数)。在进行长时间的计算之前,每个任务首先从共享资源管理器请求一个专用工作存储资源(例如:任务特定内存映射文件的视图,但我认为如果每个任务从共享堆请求一个专用内存分配,故事情节是相同的) 共享资源管理器的使用与并发::关键_部分同步,问题从这里开始:如果第一个线程/任务位于关键部分,而第二个任务发出请求,它必须等待第
Concurrency::parallel_for()
来处理一组索引任务(通常,索引集远远大于可以同时运行的线程数)。在进行长时间的计算之前,每个任务首先从共享资源管理器请求一个专用工作存储资源(例如:任务特定内存映射文件的视图,但我认为如果每个任务从共享堆请求一个专用内存分配,故事情节是相同的)
共享资源管理器的使用与并发::关键_部分同步,问题从这里开始:如果第一个线程/任务位于关键部分,而第二个任务发出请求,它必须等待第一个任务的请求得到处理。PPL显然认为:嘿,这个线程正在等待,还有更多的任务要做,因此创建了另一个线程,导致多达870个线程主要在同一个资源管理器中等待
现在,由于处理资源请求只是整个任务的一小部分,我想告诉该部分的PPL保持冷静,任何等待或协作块都不应导致新线程从工作线程的指定部分启动,我这里的问题是:是否以及如何阻止特定线程部分创建新线程,即使它以协作方式阻止。我不介意在线程处理路径下的其他块上创建新线程,但最多只能说是2*个(超)内核
到目前为止,我考虑过的备选方案:
对任务进行排队,并从数量有限的线程中处理队列。问题:我希望PPL的平行搜索引擎能够自己做到这一点
定义一个并发::可组合资源集
;在Concurrency::parallel_之外执行一次并初始化resourceSet.local()
,以将资源请求数(通过重用资源)减少到线程数(应小于任务数)。问题:此优化不会阻止多余的线程创建
为并行\u for
循环之外的每个任务预先分配所需资源。问题:这将需要太多的系统资源,而将资源量限制在线程/内核的数量是可以的(如果没有爆炸的话)
我阅读了“不要在并行循环中重复阻塞”一节,但遵循此处的建议将导致根本没有并行线程。我不知道是否可以将PPL/ConcRT配置为不使用协作同步,或者至少限制其创建的线程数。我认为这可能是通过控制,但似乎没有一个政策参数适合这个目的
但是,我有一些建议,您可能会发现这些建议有助于缓解问题,即使不是以理想的方式:
- 使用非协作同步原语来保护资源管理器,而不是
关键\u部分。我认为(尽管没有检查)古典音乐应该会成功。作为这个方向的一个激进步骤,您可以考虑为代码编写其他并行库;e、 g.(免责声明:我与之有关联)
- 在并行循环之外预先分配一些资源。每个任务不需要一个资源;每个线程一个就足够了。将这些资源放入,然后在任务内从队列中弹出一个资源,使用,然后将其推回。此外,线程可能会将资源存储在可组合的
对象中,以便在其他任务中重用,而不是将资源返回队列。如果队列恰好为空(例如,如果PPL超额订阅了机器),则可能会有不同的方法,例如在循环中旋转,直到其他线程返回资源,或者从管理器请求其他资源。此外,您还可以选择预先分配比线程数更多的资源,以最大限度地减少资源耗尽的机会
- 我的答案不是使用PPL的“解决方案”,但我认为使用线程池可以很容易地做到这一点,比如,您应该看看
<> P>这样你就可以用你的作品填充队列,这样就保证了“X”任务并行工作,其中X是“代码> Boo:::线程::HyrWorkSufCurrunyCys](<代码)>(是的Boost再次……)/P>谢谢,我会考虑和测试非合作同步。(虽然我的资源管理器也用于需要协作同步的其他上下文)、TBB以及boost::thread。我认为从任务内的队列中弹出资源也会在队列为空时启动新线程,并且(协作地)阻塞和其他任务仍在等待启动。因此,如果我迁移到TBB,那么我如何阻止特定的线程部分(lambda函数中的一部分,我将提供给parallel_)若要创建新线程,即使它以协作方式阻止?在TBB中,也不使用协作同步。如果由于并行任务中的大量阻止而导致订阅不足,我们建议用户使用更多工作线程初始化TBB。此外,由于TBB中的同步不协作,并且任务计划程序不知道存在锁因此,不建议在关键部分中使用嵌套的并行构造。因此,如果您的资源管理器在关键部分中使用并行,可能会出现一些问题。谢谢,我将再看一看boost::threads,尽管它似乎没有并行线程,所以我必须自己将一个任务集拆分为一组有限的任务范围。我刚刚发现,这与这个问题非常相似。