0 简介
很多时候我们期望调用求解器同时求解多个模型,以达到并行加速的目的。这就可以采用 C++ 多线程的工具来并行的调用 Gurobi 求解器实现这个功能。本次推文就是展示一个 demo 代码供大家参考使用。开发环境是在 GCC 11.4, C++ 11, Ubuntu 22.04, CMake 3.22 下进行的。Windows 和 Mac 环境也都是类似的。
1 多线程 std:: thread 工具简介
C++11 及其以后的版本在官方的标准库中已经拥有了较为强大的多线程工具:std::thread,这里我们先通过一个非常简单的 demo 例子说明一下如何利用 std::thread 来做多线程并行。
#include <iostream>
#include <thread>
#include <vector>
// 定义一个函数,打印 "Hello, World!"
void hello() {
std::cout << "Hello, World!" << std::endl;
}
int main() {
// 创建一个线程的向量
std::vector<std::thread> threads;
// 创建和启动 5 个线程
for (int i = 0; i < 5; ++i) {
threads.emplace_back(hello);
}
// 等待所有线程完成
for (auto& thread : threads) {
thread.join();
}
return 0;
}
想要使用 std::thread 注意需要 include 对应的头文件 <thead> 不要忘记了。以上代码就是利用 std::thread 开启了五个线程,然后并行的跑五次hello()这个函数。
需要注意的是 thread.join() 就是等待所有线程执行完毕。那么接下来我们会展示一下如何利用std::thread多线程并行的工具来实现并行调用Gurobi同时求解多个模型。
2 多线程调用 Gurobi 并行求解多个模型
以下代码就是利用多线程调用Gurobi并行加速求解多个模型的代码(这里为了方便说明,只是展示main函数,完整代码可以在公众号回复"Gurobi并行"获取):
int main(int argc, char *argv[]) {
Parser args = Parser(argc, argv); // 解析命令行参数
std::vector<GRBModel> model_list = read_model(args); // 读入多个模型
// 创建一个 vector 来存储线程
std::vector<std::thread> solver_threads;
// 使用 lambda 捕获模型引用
for (size_t i = 0; i < model_list.size(); ++i) {
solver_threads.push_back(std::thread([&model_list, i]() {
solve_model(model_list[i]);
}));
}
// 等待所有线程完成
for (auto& thr : solver_threads) {
thr.join();
}
return 0;
}
model_list 是一个 vector 里边存储的是需要求解的多个模型。
solver_threads 是一个 vector 它就是把每个线程和 solver_model() 的函数绑定在一起。
solver_model() 函数接受的参数是一个 GRBmodel 的引用,第i个线程接受到的model_list[i] 的模型,这就使得每一个 solver_model() 函数求解的是不同的模型。最后还需要 thr.join() 起到的是同步线程的作用。
3 总结
模型层面的并行加速可以在很大程度提升整体的求解速度,通过 std::thread 可以很好的去实现求解器模型层面并行加速。如需下载完整的代码,请在公众号后台回复关键词“Gurobi并行”,即可获取完整版本的代码。
微信公众号后台回复
加群:加入全球华人OR|AI|DS社区硕博微信学术群
资料:免费获得大量运筹学相关学习资料
人才库:加入运筹精英人才库,获得独家职位推荐
电子书:免费获取平台小编独家创作的优化理论、运筹实践和数据科学电子书,持续更新中ing...
加入我们:加入「运筹OR帷幄」,参与内容创作平台运营
知识星球:加入「运筹OR帷幄」数据算法社区,免费参与每周「领读计划」、「行业inTalk」、「OR会客厅」等直播活动,与数百位签约大V进行在线交流
文章须知
微信编辑:疑疑
关注我们
FOLLOW US