如何在boost.fibers中使用work_stealing调度程序

How to use the work_stealing scheduler in boost.fibers

本文关键字:work stealing 调度程序 boost fibers      更新时间:2023-10-16

我正在尝试构建一个通用的任务系统,我可以在其中发布在任何免费线程上执行的任务。通过以前的尝试,我经常用完线程,因为它们会在某个时候阻止。所以我正在尝试增强纤维;当一个纤维阻挡线程时,该线程可以在其他一些纤维上自由工作,听起来很完美。

偷工算法似乎是我目的的理想选择,但是我很难使用它。在创建示例代码纤维中,只有这样创建了线程和调度程序,因此所有纤维实际上都会在所有线程上执行。但是我想稍后启动纤维,到那时,所有其他线程都无限期地暂停,因为它们没有任何工作。我还没有找到任何再次唤醒它们的方法,我所有的纤维仅在主线程上被执行。"通知"似乎是打电话的方法,但我看不出任何方法可以真正获得算法的实例。

我尝试将指针保留到算法的所有实例上,因此我可以称为Notify(),但这并没有真正的帮助;在大多数情况下,工作线程中的算法无法从主要算法窃取任何内容,因为下一个是dispatcher_context。

我可以禁用"暂停",但是线程忙于等待,而不是一个选择。

我还尝试了共享_work-Algorithm。同样的问题,一旦线程找不到光纤,它将再也不会醒来了。我尝试了手动调用notify()的同一hack,结果,非常不可靠。

我尝试使用这些通道,但是AFAICT,如果光纤正在等待它,那么当前的上下文只是"跳动"并运行等待的光纤,以悬挂当前的上下文。

简而言之:我发现很难在另一个线程上可靠地运行光纤。当分析大多数线程时,即使我确实创建了大量的纤维。

作为一个小测试案例,我正在尝试:

std::vector<boost::fibers::future<int>> v;
for (auto i = 0; i < 16; ++i)
    v.emplace_back(boost::fibers::async([i] {
       std::this_thread::sleep_for(std::chrono::milliseconds(1000));
       return i;
    }));
int s = 0;
for (auto &f : v)
    s += f.get();

我有意使用this_thread :: sleep_for模拟CPU忙碌。

使用16个线程,我希望此代码在1s中运行,但大多数最终是16s。我能够得到这个具体的示例,可以在1秒钟内实际运行。但是,没有办法"正确",也没有办法在其他情况下工作,它总是必须被手工制作到一个特定的情况下。

我认为此示例应该按预期使用work_stealing算法工作;我想念什么?只是滥用纤维吗?我该如何可靠地实施?

谢谢dix

boost.fiber使用work_stealing算法包含一个示例(示例/work_stealing.cpp)。

  1. 您必须在应处理/窃取纤维的每个工作人员线程上安装算法。 boost::fibers::use_scheduling_algorithm< boost::fibers::algo::work_stealing >( 4); // 4 worker-threads

  2. 在处理任务/纤维之前,您必须等到在算法上注册了所有工作人员线程。该示例用于此目的。

  3. 您需要一个iDication,以确保所有工作/任务已进行,因为使用条件变量。

看一下与工作线程的运行(Boost Documentation)。