使用boost线程池时,我遇到了两个不同的问题。我正在试验我的ECS游戏引擎框架。
说明: 我正在尝试使用3个工作线程同时更新3个系统 - 我知道这是有效的,因为我已经使用了自己的线程池实现并获得了完美的结果,但由于我使用了原子,因此只有大约33%的速度。
通过一个简单的实现,我能够实现大约4倍的串行更新速度,但是我的主线程偶尔会在不让每个线程完成的情况下继续进行 - 所以我试图找到使用boost的中间点(因为我已经使用它了)在我的引擎中)但文档非常稀疏。
预期的行为是:
这是我的基本boost::asio::thread_pool
用例:
void Level::MultithreadedUpdate(const float& dt)
{
dispatch(*threadpool, [&]() {MultithreadedUpdateLogic(dt); });
dispatch(*threadpool, [&]() {MultithreadedUpdatePhysics(dt); });
dispatch(*threadpool, [&]() {MultithreadedUpdateGraphics(dt); });
threadpool->join();
}
现在我使用post
,dispatch
和defer
进行了尝试,主要是因为文档相同。
但由于这个问题的回答,我坚持派遣:Boost asio io_service dispatch vs post
这段代码不起作用,它实际上遇到了在继续之前不等待每个线程完成的相同问题,即使它实际上与它们提供的示例用例完全相同。我尝试使用.stop()
代替,奇怪的是更频繁地工作,但不是100%。
现在第二个问题(奇怪的部分):
在重构我的代码库并将线程池存储在我的引擎单例中之后,我从thread_pool
获得了完全出乎意料的行为。
我通过增加存储在数百万个组件上的整数,数千次非常快速地对单元测试更新的完整性。 MultithreadedUpdate()
成功运行一次,然后每次进行的迭代都不会运行作业。
在运行时调试线程池时,我可以看到scheduler_
(内部thread_pool
)开始积累未完成的工作1
通过boost的代码,看起来join()
最终调用stop_all_threads()
,将stopped_
设置为true
,这会阻止作业再次运行。它们不提供对可以重新启动它的任何东西的访问,并且在连续迭代stopped_
永远不会返回false
,从而阻止任何作业完成。
是否有人有关于如何使用thread_pool
或可能导致此问题的更多信息?我正在使用boost 1.66.0。
(我目前正在建立一个新的增强1.67.0,希望这是我的图书馆下载的问题)
编辑(更多信息):
我得到了与1.67.0相同的结果,我可以看到第一次迭代确实按预期工作,所有作业都按照正确的顺序完成并完成,而不会过早进行。更新结束时scheduler_.outstanding_work_
设置为0
。后续更新每次累积2次,即在每次更新结束时,每次outstanding_jobs_
计数器+= 2
,这是奇数。我确认它实际上并没有更新任何系统,其中一个作业完成而根本没有做任何事情,另外两个简单地坐在队列中。
我在这里注意到,scheduler_.task_interrupted_
也设置为true
,这对我来说没有意义,因为我从未调用过.stop()