Boost :: asio :: thread_pool奇怪的行为/怎么用?

时间:2018-04-12 15:47:47

标签: c++ multithreading boost threadpool game-engine

使用boost线程池时,我遇到了两个不同的问题。我正在试验我的ECS游戏引擎框架。

说明: 我正在尝试使用3个工作线程同时更新3个系统 - 我知道这是有效的,因为我已经使用了自己的线程池实现并获得了完美的结果,但由于我使用了原子,因此只有大约33%的速度。

通过一个简单的实现,我能够实现大约4倍的串行更新速度,但是我的主线程偶尔会在不让每个线程完成的情况下继续进行 - 所以我试图找到使用boost的中间点(因为我已经使用它了)在我的引擎中)但文档非常稀疏。

预期的行为是:

  1. 更新逻辑
  2. 更新物理
  3. 更新图形
  4. 等待所有工作完成然后继续。
  5. 这是我的基本boost::asio::thread_pool用例:

    void Level::MultithreadedUpdate(const float& dt)
    {
        dispatch(*threadpool, [&]() {MultithreadedUpdateLogic(dt); });
        dispatch(*threadpool, [&]() {MultithreadedUpdatePhysics(dt); });
        dispatch(*threadpool, [&]() {MultithreadedUpdateGraphics(dt); });
        threadpool->join();
    }
    

    现在我使用postdispatchdefer进行了尝试,主要是因为文档相同。

    但由于这个问题的回答,我坚持派遣: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()

0 个答案:

没有答案