为何C++中std::async执行1024次函数未比串行调用更快?
问题分析与解决
核心问题
你的并行代码逻辑存在关键错误:在atoi(argv[1]) == 1的分支中,std::future<int> result是循环体内的局部变量。每次循环迭代结束时,该std::future对象会被销毁,而std::future的析构函数会阻塞当前线程,直到关联的异步任务执行完成。这就导致你创建的每个异步任务都被强制串行执行——前一个任务完成后,才会创建下一个任务,最终耗时和串行调用几乎一致。
修正方案
需要将所有异步任务对应的std::future对象保存到一个容器中,等所有任务都创建完成后,再统一等待它们执行结束。这样才能让多个任务真正并行运行。
修正后的代码
#include <chrono> #include <cstdio> #include <future> #include <thread> #include <vector> struct Timer { std::chrono::time_point<std::chrono::steady_clock> start, end; std::chrono::duration<float> duration{}; Timer() { start = std::chrono::high_resolution_clock::now(); } ~Timer() { end = std::chrono::high_resolution_clock::now(); duration = end - start; printf("Duration %f s\n", duration.count()); } }; int add(int a, int b) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); return a + b; } int main(int argc, char* argv[]) { if(argc != 2) { printf("Usage: %s <n>\n where n is 0 or 1\n\n", argv[0]); return 1; } Timer timer; if(atoi(argv[1]) == 0) { for(int i = 0; i < 1024; i++) { add(i, 1024); } } if(atoi(argv[1]) == 1) { std::vector<std::future<int>> futures; futures.reserve(1024); // 预分配空间,避免动态扩容开销 for(int i = 0; i < 1024; i++) { futures.emplace_back(std::async(std::launch::async, add, i, 1024)); } // 这里不需要显式调用get(),vector销毁时会自动等待所有future完成 // 如果需要获取结果,可以遍历调用result.get() // for(auto& f : futures) { f.get(); } } return 0; }
预期效果
修正后,并行执行的耗时会显著降低,大致接近(1024 * 10ms) / CPU核心数(实际会略高,包含线程调度开销)。比如8核CPU下,耗时大概在13秒左右(你的串行测试是16秒,debug模式下线程调度开销会更大)。
额外说明
- 你的CMake配置没有问题,已经正确指定了C++20标准,满足
std::async的使用要求。 - 使用
std::launch::async确保任务会在新线程执行,避免编译器选择std::launch::deferred(延迟执行,直到调用get()才会在当前线程运行)。
内容的提问来源于stack exchange,提问作者Kérdezősködő Indián
相关产品推荐
相关产品推荐

