TBB 线程池意外增加
Posted
技术标签:
【中文标题】TBB 线程池意外增加【英文标题】:TBB thread pool unexpectedly increasing 【发布时间】:2016-06-24 13:52:12 【问题描述】:我们有一段代码利用 TBB 生成任务来执行一些处理,这是使用以下 TBB 代码初始化 TBB 线程池完成的:
tbb::task_scheduler_init(8);
然后对于我们想要生成的每个任务,我们使用以下代码(其中 MainTask 派生自 tbb::task 类):
task = new (tbb::task::allocate_root()) MainTask(theAction, theOutputData);
tbb::task::enqueue(*task);
当我们运行我们的代码时,我们从一个线程池开始,该线程池与预期的内核数量(在我们的例子中为 8 个线程)相同,但随着程序执行并产生新的 TBB 任务,如上所述,数量某些随机点的线程数突然增加。程序执行 40 分钟后,线程数从 8 个增加到 15 个。
为什么会这样? TBB 不应该将工作线程的数量固定为等于内核的数量吗?
【问题讨论】:
是否有可能在 TBB 外部创建线程?线程是一种系统资源,程序的任何其他部分都可以创建它们。 如果你new
-编辑了task
,你在哪里delete
呢?
【参考方案1】:
正如我在另一个回答中所说的那样:别担心 :-)
TBB 可以很好地防止实际的超额订阅 - 您的程序中同时只有 8 个线程处于活动状态。尽管由于各种原因,它有时需要比硬件资源更多的线程。一个例子是tbb::task_arena
,没有保留主插槽,另一个最近添加的是tbb::global_control
类,它允许动态更改池中活动线程的数量。不幸的是,TBB 的实现方式为数据竞赛留下了一些空间。当一些线程在返回线程池的途中进入休眠状态,而新工作到达并请求所有 8 个线程立即开始处理时,就会发生这种情况;但这些处于中间状态的线程尚未计入线程池,而是创建了新线程。
TBB 尽可能减少了此数据争用的窗口,但要完全关闭它,需要在热路径上进行同步,这会影响总体性能。因此,我们决定允许数据竞争并减少热路径上的障碍。
不过,别担心,没有资源泄漏,因为 TBB 对它可以通过这种方式创建的最大线程数有硬性限制。根据平台的不同,这个数字从 2 倍到 4 倍不等(尽管内部实现细节不断变化)。
不过,我很惊讶它创建了 15 个线程,而且我理解您的担忧。如果您与他们共享复制器,TBB 团队将不胜感激。您可以通过TBB Forum 或OSS site 贡献复制者。
【讨论】:
感谢您的帮助,但我们有几个后续问题。 1.什么是复制器。 2.我们如何创建并提交? @S.J.Thunderstick 复制器是重现问题的最小测试。您创建测试并将其发布在论坛上或作为贡献发布。但同样,这并不是什么大问题——既不是泄漏也不是超额订阅以上是关于TBB 线程池意外增加的主要内容,如果未能解决你的问题,请参考以下文章