【问题标题】:intel tbb memory overheadintel tbb 内存开销
【发布时间】:2017-03-03 16:43:18
【问题描述】:

在重用使用英特尔 TBB 函数的线程时,我们会遇到高内存开销。我们预计一旦线程完成给定的工作负载,它将释放相应的内存。然而,情况似乎并非如此,即使线程执行工作单元之间存在长时间的停顿。

我们准备了一个例子来说明问题:

int main() {
   blocking_queue<size_t> command_input_queue;
   tbb::atomic<size_t> count = 1;
   //workers
   std::vector<std::thread> worker;
   for(size_t i = 0; i < 15; i++) {
      worker.push_back(std::thread([&command_input_queue, &count](){
        while(true)
        {
            size_t size;
            //wait for work..
            command_input_queue.wait_and_pop(size);
            //do some work with Intel TBB
            std::vector<int32_t> result(size);
            for(size_t i = 0; i < result.size(); i++) {
                result[i] =  i % 1000;
            }
            tbb::parallel_sort(result.begin(), result.end());
            size_t local_count = count++;
            std::cout << local_count << " work items executed " << std::endl;
        }
    }));
   }
   //enqueue work
   size_t work_items = 15;
   for(size_t i = 0; i < work_items   ; i++) {
      command_input_queue.push(10 * 1000 * 1000);
   }

   while(true) {
      boost::this_thread::sleep( boost::posix_time::seconds(1) );
      if(count > 15) {
         break;
      }
   }
   //wait for more commands
   std::cout << "Wait" << std::endl;
   boost::this_thread::sleep( boost::posix_time::seconds(60) );

   //----!During the wait, while no thread is active, 
   //the process still claims over 500 MB of memory!----
   for(size_t i = 0; i < 15; i++) {
     command_input_queue.push(1000 * 1000);
   }
...

在示例中,我们启动了 15 个工作线程。他们等待任务并执行 tbb::parallel_sort 并在完成后释放所有资源。 问题是在处理完所有任务并且所有工作人员都在等待新任务之后,该进程仍然需要 500MB 的内存。

像 valgrind's massif 这样的工具并没有告诉我们内存在哪里被占用。 我们将程序与 libtbb.so 相关联。所以 tbb 分配器应该不是问题。

有人知道我们如何在工作人员空闲时释放内存吗?

【问题讨论】:

  • 我接受了你的测试,稍微修改了一下(用 tbb::concurrent_bounded_queue 替换了 blocking_queue,用 std::this_thread::sleep_for 替换了 boost::this_thread_sleep),并用 Visual Studio 2015 和 Intel TBB 编译2017 年更新 2。结果测试在峰值使用约 500MB,但在主线程开始等待时迅速下降到约 1.7MB - 即问题未重现。
  • 感谢您尝试重现该问题。我也在 Ubuntu 14.04 上使用 TBB 2017 进行了测试。在我的系统上,即使我运行您修改后的测试,内存消耗也没有完成。但是在调用malloc_trim(见下面的答案)之后,它会下降到~2MB。所以它似乎依赖于系统。

标签: c++ multithreading tbb


【解决方案1】:

调用deletefree 后,堆分配的内存通常不会返回给操作系统。您需要调用 malloc_trim 或您的分配器特定函数来执行此操作。

【讨论】:

  • 谢谢!这解决了这个问题。在等待之前调用 malloc_trim 可将内存消耗减少到 ~2MB。
【解决方案2】:

尽管有连接的分配器,但 TBB 调度程序缓存任务分配,尽管它没有解释 500MB。可以解释的是,TBB 动态加载 TBB 分配器,它当然会缓存内存,如果它可以在 libtbb.so 旁边找到它的话。可以通过设置env var TBB_VERSION=1来检查tbbmalloc是否被激活

在我看来很奇怪的是,为什么在 TBB 创建自己的工作线程时,您使用工作线程超额订阅机器?

【讨论】:

  • 你是对的,我们在这个例子中超额订阅。该示例只是复杂系统的简化提取。因此,我不能简单地更改实现的那部分。
猜你喜欢
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 2011-10-10
  • 1970-01-01
  • 2020-10-27
  • 2011-11-16
相关资源
最近更新 更多