【发布时间】: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