Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 并发::parallel_for(PPL)正在创建太多线程_C++_Multithreading_Concurrency_Ppl - Fatal编程技术网

C++ 并发::parallel_for(PPL)正在创建太多线程

C++ 并发::parallel_for(PPL)正在创建太多线程,c++,multithreading,concurrency,ppl,C++,Multithreading,Concurrency,Ppl,我正在使用Visual Studio 2010的并行模式库(PPL)的Concurrency::parallel_for()来处理一组索引任务(通常,索引集远远大于可以同时运行的线程数)。在进行长时间的计算之前,每个任务首先从共享资源管理器请求一个专用工作存储资源(例如:任务特定内存映射文件的视图,但我认为如果每个任务从共享堆请求一个专用内存分配,故事情节是相同的) 共享资源管理器的使用与并发::关键_部分同步,问题从这里开始:如果第一个线程/任务位于关键部分,而第二个任务发出请求,它必须等待第

我正在使用Visual Studio 2010的并行模式库(PPL)的
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,尽管它似乎没有并行线程,所以我必须自己将一个任务集拆分为一组有限的任务范围。我刚刚发现,这与这个问题非常相似。