Memory tbb::用于在具有80个内核的机器上耗尽内存的并行_

Memory tbb::用于在具有80个内核的机器上耗尽内存的并行_,memory,multicore,tbb,parallel-for,Memory,Multicore,Tbb,Parallel For,我试图在一台有160个并行线程(8个Intel E7-8870)和0.5 TB内存的机器上使用tbb::parallel_for。它是一个当前的Ubuntu系统,内核为3.2.0-35-generic#55 Ubuntu SMP。TBB来自软件包libtbb2版本4.0+r233-1 即使是一个非常简单的任务,我也会耗尽资源,要么是“bad_alloc”,要么是“thread_monitor Resource Temporary unavailable”。我把它归结为一个非常简单的测试: #in

我试图在一台有160个并行线程(8个Intel E7-8870)和0.5 TB内存的机器上使用tbb::parallel_for。它是一个当前的Ubuntu系统,内核为3.2.0-35-generic#55 Ubuntu SMP。TBB来自软件包libtbb2版本4.0+r233-1

即使是一个非常简单的任务,我也会耗尽资源,要么是“bad_alloc”,要么是“thread_monitor Resource Temporary unavailable”。我把它归结为一个非常简单的测试:

#include <vector>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "tbb/tbb.h"
#include "tbb/task_scheduler_init.h"
using namespace tbb;

class Worker
{
  std::vector<double>& dst;
 public:
  Worker(std::vector<double>& dst)
    : dst(dst)
    {}

  void operator()(const blocked_range<size_t>& r ) const
  {
    for (size_t i=r.begin(); i!=r.end(); ++i)
      dst[i] = std::sin(i);
  }
};

int main(int argc, char** argv)
{
  unsigned int n = 10000000;
  unsigned int p = task_scheduler_init::default_num_threads();

  std::cout << "Vector length: " << n << std::endl
            << "Processes    : " << p << std::endl;

  const size_t grain_size = n/p;
  std::vector<double> src(n);

  std::cerr << "Starting loop" << std::endl;
  parallel_for(blocked_range<size_t>(0, n, grain_size), RandWorker(src));
  std::cerr << "Loop finished" << std::endl;
}
错误是随机出现的,并且随着n的增大,出现的频率也会增加。这里1000万的价值是它们经常发生的一个点。然而,考虑到机器的特性,这应该不会耗尽内存(我在这些测试中单独使用它)

晶粒度是在tbb创建了太多的Worker实例之后引入的,这使得它在更小的n中失败


有人能建议如何设置tbb来处理大量线程吗?

在回答中的评论中总结讨论:

消息“thread_monitor Resource在pthread_create中暂时不可用”基本上说明TBB无法创建足够的线程;“资源暂时不可用”是
strerror()
pthread\u create()
返回的错误代码报告的内容。此错误的一个可能原因是内存不足,无法为新线程分配堆栈。默认情况下,TBB为工作线程请求4M堆栈;如有必要,可使用参数将此值调整为
tbb::task\u scheduler\u init
构造函数


正如Guido Kanschat所报告的那样,在这种特殊情况下,问题是由于意外设置了
ulimit
,限制了进程可用的内存。

在回答中的评论中总结了讨论:

消息“thread_monitor Resource在pthread_create中暂时不可用”基本上说明TBB无法创建足够的线程;“资源暂时不可用”是
strerror()
pthread\u create()
返回的错误代码报告的内容。此错误的一个可能原因是内存不足,无法为新线程分配堆栈。默认情况下,TBB为工作线程请求4M堆栈;如有必要,可使用参数将此值调整为
tbb::task\u scheduler\u init
构造函数


正如Guido Kanschat所报告的那样,在这种特殊情况下,问题是由
ulimit
意外设置造成的,该设置限制了进程可用的内存。

是否编译64位程序并使用相应的TBB版本?如果从threadingbuildingblocks.org获取最新的TBB二进制文件,问题是否会重现?您的类被命名为Worker,但在并行情况下,您可以使用RandWorker;这仅仅是因为你在发布之前清理了代码,忘记了在某个地方重命名吗?Alexey,类名的冲突确实是由于清理造成的。我刚刚在删除“Rand”后重新编译,断言它是64位模式,并使用了最新的二进制文件。我看到了这些变化:首先,程序运行起来似乎没有更频繁地崩溃。第二,如果没有,则错误消息更为明确:“pthread_create中的thread_monitor Resource暂时不可用”该消息基本上告诉TBB无法创建足够的线程;“资源暂时不可用”是
strerror()
pthread\u create()
返回的错误代码报告的内容。我建议编写一个简单的测试,不使用TBB,什么也不做,只创建尽可能多的线程。还可以尝试改变堆栈大小(通过线程属性)。默认情况下,TBB为每个线程请求4M堆栈;也许在你的情况下,一个较小的值就足够了?很抱歉问了两次关于64位的问题-我忘了我已经问过了。通常你不需要因为机器的尺寸而做任何事情;它应该会起作用。对于进一步的故障排除,我认为TBB论坛可能是一个更好的场所。令人尴尬的是,你走对了方向。我的帐户上有一个ulimit,它是为另一台计算机设置的。6GB。我刚刚用1G的向量长度和1000个线程运行了相同的程序。谢谢你的帮助,很抱歉没有早点找到!您是否编译64位的程序并使用相应的TBB版本?如果从threadingbuildingblocks.org获取最新的TBB二进制文件,问题是否会重现?您的类被命名为Worker,但在并行情况下,您可以使用RandWorker;这仅仅是因为你在发布之前清理了代码,忘记了在某个地方重命名吗?Alexey,类名的冲突确实是由于清理造成的。我刚刚在删除“Rand”后重新编译,断言它是64位模式,并使用了最新的二进制文件。我看到了这些变化:首先,程序运行起来似乎没有更频繁地崩溃。第二,如果没有,则错误消息更为明确:“pthread_create中的thread_monitor Resource暂时不可用”该消息基本上告诉TBB无法创建足够的线程;“资源暂时不可用”是
strerror()
pthread\u create()
返回的错误代码报告的内容。我建议编写一个简单的测试,不使用TBB,什么也不做,只创建尽可能多的线程。还可以尝试改变堆栈大小(通过线程属性)。默认情况下,TBB为每个线程请求4M堆栈;也许在你的情况下,一个较小的值就足够了?很抱歉问了两次关于64位的问题-我忘了我已经问过了。通常你不需要因为机器的尺寸而做任何事情;它应该会起作用。对于进一步的故障排除,我认为TBB论坛可能是一个更好的场所。令人尴尬的是,你走对了方向。我的帐户上有一个ulimit,它是为另一台计算机设置的。6GB。我刚刚用1G的向量长度和1000个线程运行了相同的程序。谢谢你的帮助,很抱歉没有早点找到!
Vector length: 10000000
Processes    : 160
Starting loop
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable