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

C++多线程程序运行耗时比单线程更长的原因排查

多线程版本性能反低于单线程的核心原因
  • 计时API使用错误
    你代码中用的clock()函数统计的是进程所有线程占用的CPU时间总和,不是现实中流逝的墙钟时间。当两个线程并行运行在不同CPU核心上时,两个线程的CPU耗时会被累加计算:比如两个线程各跑了4秒,clock()返回的时间差就会是8秒左右,和你测得的8.5秒结果吻合。单线程版本是顺序执行代码,CPU时间和实际流逝时间一致,所以显示为4.96秒。这个计时结果本身就不能用来对比多线程和单线程的实际运行速度,要测真实耗时应该使用std::chrono::steady_clock这类墙钟计时器。

  • 伪共享(False Sharing)带来巨量额外开销
    代码中even_sum和odd_sum是连续声明的全局变量,内存地址紧挨着,几乎一定会落在同一个CPU缓存行(主流CPU的缓存行大小为64字节)。两个运行在不同核心的线程频繁修改这两个变量时,CPU的MESI缓存一致性协议会不断在两个核心之间来回转移该缓存行的所有权:核心1修改even_sum后,核心2对应的缓存行会失效,必须重新从内存/其他核心同步数据;核心2修改odd_sum后,核心1的缓存行又会失效。这种反复的缓存同步开销远大于循环、奇偶判断、计数本身的计算量,直接抵消了多线程的并行收益,甚至带来额外的性能损耗。

  • 任务拆分逻辑不合理
    你当前的多线程实现中,两个线程各自完整遍历了1~1000000000的全量区间,一个只统计偶数、一个只统计奇数,总循环次数和单线程版本完全一致(都是20亿次循环),根本没有通过并行减少计算总量。正确的拆分方式应该是把待遍历的数值区间切分成多段,每个线程只处理自己负责的区间段,同时统计段内的奇数和偶数,总循环次数可以直接降到10亿次,才能真正发挥多线程的并行优势。

修正后参考代码

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;

// 按缓存行大小对齐,彻底避免伪共享
struct alignas(64) RangeResult {
    long long even_cnt = 0;
    long long odd_cnt = 0;
};

void countInRange(int start, int end, RangeResult& res) {
    for (int i = start; i < end; ++i) {
        if (i % 2 == 0) {
            res.even_cnt++;
        } else {
            res.odd_cnt++;
        }
    }
}

void multiThreadVersion() {
    RangeResult res1, res2;
    // 把10亿数据拆成两半分给两个线程
    thread t1(countInRange, 1, 500000000, ref(res1));
    thread t2(countInRange, 500000000, 1000000000, ref(res2));
    t1.join();
    t2.join();
    long long total_even = res1.even_cnt + res2.even_cnt;
    long long total_odd = res1.odd_cnt + res2.odd_cnt;
    cout << total_even << " " << total_odd << endl;
}

void singleThreadVersion() {
    RangeResult res;
    countInRange(1, 1000000000, res);
    cout << res.even_cnt << " " << res.odd_cnt << endl;
}

int main() {
    auto start = chrono::steady_clock::now();
    // 切换注释测试不同版本
    multiThreadVersion();
    // singleThreadVersion();
    auto end = chrono::steady_clock::now();
    double cost_ms = chrono::duration_cast<chrono::milliseconds>(end - start).count();
    cout << "耗时: " << cost_ms / 1000.0 << "s" << endl;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:24:31