我正在尝试构建一个通用的任务系统,在这个系统中,我可以发布在任意线程上执行的任务。在之前的尝试中,我经常没有线程,因为它们会在某个时候阻塞。因此,我正在尝试促进纤维;当一根纤维阻塞,线程可以自由地在其他纤维上工作,听起来很完美。
偷工作算法似乎对我的目的来说是理想的,但我很难使用它。在这个例子中,代码纤维被创建,只有这样线程和调度器才被创建,所以所有的纤维实际上都在所有的线程上被执行。但是我想稍后启动光纤,到那时所有其他线程都会被无限期地挂起,因为它们没有任何工作。我没有找到任何方法再次唤醒他们,我所有的纤维只能在主线程上执行。“通知”似乎是调用的方法,但我看不到有任何方法能够真正找到一个算法的实例。
我试着保存指向该算法所有实例的指针,这样我就可以调用notify(),但这并没有真正的帮助;大多数情况下,工作线程中的算法不能从主线程中窃取任何东西,因为下一个是dispatcher_context。
我可以禁用“挂起”,但是线程正忙着等待,这不是一个选项。
我还尝试了共享工作算法。同样的问题,一旦一根线找不到一根纤维,它就再也不会醒来了。我尝试了相同的黑客手动调用通知(),同样的结果,非常不可靠。
我试着使用频道,但是AFAICT,如果有光纤在等待,当前的上下文就会“跳过”,运行等待的光纤,挂起当前的光纤。
简而言之:我发现很难在另一个线程上可靠地运行一个光纤。在分析时,大多数线程只是在等待一个condition_variable,尽管我确实创建了大量的光纤。
作为一个小测试用例,我正在尝试:
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中运行,但大多数情况下它是16 s。我能够让这个具体的例子在1中真正运行,只是黑客入侵一些东西;但是没有办法感觉“正确”,也没有办法在其他情况下有效,它总是要手工制作到一个特定的场景中。
我认为这个例子应该和work_stealing算法一样工作;我缺少了什么呢?这只是滥用纤维吗?我如何可靠地实现这一点?
谢谢你,迪克斯
发布于 2017-12-13 14:40:06
boost.fiber包含一个使用work_stealing算法的示例(示例/work_stealing.cpp)。
boost::fibers::use_scheduling_algorithm< boost::fibers::algo::work_stealing >( 4); // 4 worker-threads
看看使用工作线程运行 (boost文档)。
https://stackoverflow.com/questions/47773921
复制相似问题