You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何教程中的C++多线程求和示例运行慢于单线程?

多线程计算奇偶和反而比单线程慢的原因分析

我跟着教程写了一段C++代码,用来计算0到1900000000范围内的奇数和与偶数和。单线程版本跑3秒,但多线程版本居然要18秒——我用的是多核CPU,完全搞不懂为什么会这样,明明预期多线程更快才对。

代码如下:

#include <iostream>
#include <thread>
#include <chrono>
#include <algorithm>


unsigned long long OddSum = 0;
unsigned long long EvenSum = 0;

void findEven(unsigned long long start, unsigned long long end){
    for (unsigned long long i = start; i <= end; i++){
        if((i & 1)==0){
            EvenSum += i;
        }
    }
}


void findOdd(unsigned long long start, unsigned long long end){
    for (unsigned long long i = start; i <= end; i++){
        if((i & 1)==1){
            OddSum += i;
        }
    }
}

int main(){
    unsigned long long start = 0, end = 1900000000;

    auto startTime = std::chrono::high_resolution_clock::now();

    std::thread t1(findEven, start, end);
    std::thread t2(findOdd, start, end);

    t1.join();
    t2.join();

    // findOdd(start, end);
    // findEven(start, end);


    auto stopTime = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stopTime - startTime);

    std::cout << "OddSum : " << OddSum << std::endl;
    std::cout << "EvenSum : " << EvenSum << std::endl;

    std::cout << "Sec : " << duration.count()/1000000 << std::endl;


    return 0;
}

问题根源

  • 伪共享(缓存行竞争):全局变量OddSum和EvenSum大概率被分配到同一个CPU缓存行(通常64字节)。两个线程分别对这两个变量做累加时,每次写入都会让整个缓存行失效,CPU核心之间得不断同步缓存数据,这带来的开销远大于多线程并行的收益。
  • 重复遍历导致工作量翻倍:单线程是遍历一次区间同时计算奇偶和,而多线程版本是两个线程各自完整遍历一遍整个范围,总工作量直接翻了一倍,再加上缓存竞争的拖累,速度自然暴跌。

优化方案

  1. 解决伪共享:让两个全局变量各自独占一个缓存行,比如用C++11的alignas属性:
alignas(64) unsigned long long OddSum = 0;
alignas(64) unsigned long long EvenSum = 0;

或者用GCC编译器的特定属性:

unsigned long long OddSum __attribute__((aligned(64))) = 0;
unsigned long long EvenSum __attribute__((aligned(64))) = 0;
  1. 拆分任务区间:不要让两个线程重复遍历,而是把区间拆分成两部分,比如一个线程处理0949999999,另一个处理9500000001900000000,每个线程同时计算自己区间内的奇偶和,最后汇总结果。这样既减少了总遍历次数,也避免了缓存竞争。

  2. 用数学公式直接计算(最优解):奇偶和完全可以用等差数列公式直接算出,根本不需要循环:

  • 偶数和:0到N的偶数构成首项0、末项为N - (N%2)、公差2的等差数列,项数是(末项/2)+1,和为(0 + 末项) * 项数 / 2
  • 奇数和:1到N的奇数构成首项1、末项为N - (1 - N%2)、公差2的等差数列,项数是(末项 + 1)/2,和为项数 * 项数(因为1+3+5+...+(2k-1)=k²)
    这种方法耗时几乎可以忽略,比任何循环版本都高效。

内容的提问来源于stack exchange,提问作者bevenstee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 15:57:40