Mac下C++多线程并行耗时高于串行的问题求助
Mac上C++多线程求和反而比串行慢的问题
我在Mac上首次尝试C++多线程编程,实现奇偶数值求和功能,但发现多线程版本耗时反而比串行版本更长,不符合预期。
实现代码
#include <iostream> #include <thread> #include <chrono> using namespace std; using namespace chrono; const long long maxLimit = 2e9; void getEvenSum(long long &sum) { for(int i = 0 ; i <= maxLimit ; i+=2) { sum += i; } } void getOddSum(long long &sum) { for(int i = 1 ; i <= maxLimit ; i+=2) { sum += i; } } int main() { auto startTime = high_resolution_clock::now(); long long evenSum = 0 , oddSum = 0; thread evenSumThread(getEvenSum, ref(evenSum)); thread oddSumThread(getOddSum, ref(oddSum)); evenSumThread.join(); oddSumThread.join(); auto endTime = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(endTime - startTime); cout << " final sum is " << evenSum << " " << oddSum << endl; cout << " time taken with thread :" << duration.count() / (long double)1e6 << endl; startTime = high_resolution_clock::now(); evenSum = 0 , oddSum = 0; getEvenSum(evenSum); getOddSum(oddSum); endTime = high_resolution_clock::now(); duration = duration_cast<microseconds>(endTime - startTime); cout << " final sum is " << evenSum << " " << oddSum << endl; cout << " time taken without thread " << duration.count() / (long double)1e6 << endl; return 0; }
运行输出
final sum is 1000000001000000000 1000000000000000000 time taken with thread :5.01665 final sum is 1000000001000000000 1000000000000000000 time taken without thread 2.83442
已尝试的解决方案
- 使用
g++ --std=c++11 file.cpp编译 - 使用
g++ --std=c++11 -O3 -s -DNDEBUG file.cpp编译(耗时有波动但仍长于串行) - 使用
g++ --std=c++17 file.cpp编译 - 尝试
clang++ -std=c++11 file.cpp编译(提示CLANG不存在) - 尝试修改XCode->Product->Scheme->Change Scheme(无对应菜单)
- 在VS Code和iTerm中切换DEBUG/RELEASE模式
注:该代码2年前在Linux环境下运行正常,并行版本性能优于串行。
问题分析与解决建议
1. 编译器识别问题
Mac上默认的g++其实是clang的别名,你可以通过g++ --version确认。提示CLANG不存在大概率是输入错误,正确命令是clang++,或者直接用g++即可(它指向clang)。
2. 编译器优化差异(核心原因)
你的累加逻辑非常简单,编译器在串行模式下可能直接用数学公式替换了循环:
- 偶数和公式:
(maxLimit/2) * (maxLimit/2 + 1) - 奇数和公式:
(maxLimit/2) * (maxLimit/2)(当maxLimit为偶数时)
在-O3优化级别下,串行版本的getEvenSum和getOddSum会被编译器彻底优化成直接计算结果的代码,完全跳过循环。但多线程版本中,线程函数的调用+引用传递的特性,会让编译器难以进行这种激进优化,只能实际执行循环累加,导致耗时反而更长。
你可以通过生成汇编代码验证这一点:执行g++ --std=c++17 -O3 -S file.cpp,对比串行和多线程版本中getEvenSum的汇编代码,会发现串行版本的函数几乎没有循环指令。
3. 线程调度与缓存影响
Mac的线程调度机制和Linux存在差异,线程创建、上下文切换的开销可能更高。另外,两个线程累加操作虽然没有共享内存,但连续的循环可能会竞争CPU缓存资源,进一步放大耗时差异。
解决办法
- 替换为数学公式计算:如果只是为了得到结果,直接用公式替代循环,无论串行还是并行都会极快,但这可能偏离你学习多线程的初衷。
- 调整测试任务类型:选择更适合并行的计算密集型任务(比如大数组的元素运算、矩阵乘法等),这类任务无法被编译器用简单公式优化,能真正体现多线程的性能优势。
- 优化多线程编译选项:尝试添加
-pthread编译选项,命令:g++ --std=c++17 -O3 -pthread file.cpp,确保线程库被正确链接和优化。 - 禁用部分优化验证:可以用
-fno-inline选项禁止函数内联,对比串行和多线程版本的耗时,验证是否是优化差异导致的问题。
内容的提问来源于stack exchange,提问作者Neer Patel
相关产品推荐
相关产品推荐

