C++混用deferred与async和仅用async耗时无差异问题排查
问题根因
- 存在多余同步计算:循环内第一行
objects[i].generateNumbers()已经同步执行了一遍随机数生成逻辑,这部分耗时占总耗时的绝大部分,完全掩盖了后续异步逻辑的性能差异,同时属于无意义的重复计算。 - 未实现真正的并行执行:创建
std::future后立刻调用get()会阻塞主线程,直到当前任务执行完成再进入下一轮循环,无论使用哪种启动策略,所有任务都是串行执行,自然不会有性能差异。 - 附加问题:
rand()为线程不安全函数,多线程并发调用会产生数据竞争,也会干扰性能测试结果,建议替换为C++11<random>库提供的线程安全随机数生成器。
修正后的代码
#include <iostream> #include <chrono> #include <future> #include <vector> using namespace std; class RandomNumberGenerator { public: enum class task { LIGHT, HEAVY }; task taskType; RandomNumberGenerator(): taskType(task::LIGHT) { int rnd = rand() % 2; taskType = (rnd == 0) ? task::LIGHT : task::HEAVY; } bool generateNumbers() { int number; if(taskType == task::LIGHT) { for (int i = 0; i < 100; i++) { number = rand(); } } else { for (int i = 0; i < 1000000; i++) { number = rand(); } } return true; } }; int main() { cout << "Starting to generate numbers\n"; RandomNumberGenerator objects[100]; vector<future<bool>> futures; futures.reserve(100); auto start = chrono::system_clock::now(); // 先启动所有异步任务,不阻塞 for (int i = 0; i < 100; i++) { if (objects[i].taskType == RandomNumberGenerator::task::LIGHT) { futures.push_back(async(launch::deferred, &RandomNumberGenerator::generateNumbers, &objects[i])); } else { futures.push_back(async(launch::async, &RandomNumberGenerator::generateNumbers, &objects[i])); } // 全async方案替换为下面一行 // futures.push_back(async(launch::async, &RandomNumberGenerator::generateNumbers, &objects[i])); } // 所有任务启动完成后再逐个获取结果 for (auto& fut : futures) { bool result = fut.get(); } auto end = chrono::system_clock::now(); cout << "Total time = " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " 毫秒\n"; return 0; }
修正后即可观测到两种启动策略的性能差异:混用deferred的方案因为轻量任务避免了线程创建、调度的额外开销,耗时会明显低于全async方案。
内容的提问来源于stack exchange,提问作者norepine phrine
相关产品推荐
相关产品推荐

