重新使用使用英特尔TBB功能的线程时,我们遇到高内存开销。我们预计一旦某个线程完成了给定的工作负载,就会释放相应的内存。但是,这似乎并不是这种情况,即使线程执行工作单元之间有很长时间的停顿。英特尔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的地块这样的工具没有告诉我们内存在哪里。 我们将程序与libtbb.so链接起来。所以tbb分配器不应该成为问题。
有人知道我们如何释放内存,而工人闲置吗?
我把你的测试修改了一下(用tbb :: concurrent_bounded_queue代替blocking_queue,用std :: this_thread :: sleep_for代替boost :: this_thread_sleep),并用Visual Studio 2015和Intel TBB 2017 Update 2编译。最终的测试在峰值时使用了〜500MB,但是当主线程开始等待时,快速降低到〜1.7MB--即问题未被复制。 –
感谢您付出努力尝试重现此问题。我在TBB 2017上也在Ubuntu 14.04上进行了测试。 在我的系统上,即使运行修改后的测试,内存消耗也没有完成。但是在调用'malloc_trim'(见下面的答案)之后,它会下降到〜2MB。所以它似乎是依赖于系统的。 –