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

并行循环中正确使用std::atomic<double>,C++17/20有无内置实现?

问题分析与解决方案

原代码的线程安全问题

原代码中,对std::atomic<double>的if (s > max_value) { max_value = s; }并非原子操作。多线程环境下会出现竞态:比如线程A读取max_value为0,判断s=1符合更新条件,还未完成赋值时,线程B已将max_value更新为2;随后线程A把max_value设为1,直接覆盖了正确的最大值,导致结果错误。

正确实现方式

方式1:原子CAS操作修复

使用std::atomic的compare_exchange_weak(或compare_exchange_strong)实现原子性的条件更新。该操作会原子性地比较当前值与预期值,若相等则更新为新值,否则刷新预期值并重试:

#include <iostream>
#include <atomic>
#include <vector>
#include <algorithm>
#include <execution>

int main()
{
    constexpr int vec_size = 2000000;
    std::vector<double> numbers(vec_size, 1.0);
    numbers[vec_size / 2] = 2.0;
    std::atomic<double> max_value{ 0.0 };

    std::for_each(std::execution::par_unseq, numbers.begin(), numbers.end(), [&max_value](double s) {
        double current_max = max_value.load();
        while (s > current_max && !max_value.compare_exchange_weak(current_max, s)) {
            // 预期值已过时,循环重试
        }
        });

    std::cout << "Max Value: " << std::fixed << max_value;
    return 0;
}

方式2:使用C++17并行算法(更推荐)

C++17引入了带执行策略的标准算法,其中std::reduce或std::max_element的并行版本会自动处理线程安全,无需手动管理原子操作:

用std::reduce计算最大值

#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>
#include <numeric>
#include <limits>

int main()
{
    constexpr int vec_size = 2000000;
    std::vector<double> numbers(vec_size, 1.0);
    numbers[vec_size / 2] = 2.0;

    // 用并行reduce计算最大值,初始值设为double的最小值
    double max_value = std::reduce(std::execution::par_unseq, 
                                   numbers.begin(), numbers.end(),
                                   std::numeric_limits<double>::lowest(),
                                   [](double a, double b) { return std::max(a, b); });

    std::cout << "Max Value: " << std::fixed << max_value;
    return 0;
}

用并行版std::max_element

#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>

int main()
{
    constexpr int vec_size = 2000000;
    std::vector<double> numbers(vec_size, 1.0);
    numbers[vec_size / 2] = 2.0;

    auto max_it = std::max_element(std::execution::par_unseq, numbers.begin(), numbers.end());
    std::cout << "Max Value: " << std::fixed << *max_it;
    return 0;
}

C17/C20的内置支持

C++17已经内置了完整的并行算法支持(需编译器支持并链接对应并行库,比如GCC的-ltbb):

  • std::max_element:支持std::execution::par/std::execution::par_unseq执行策略,内部会安全完成并行最大值计算;
  • std::reduce:通用并行归约算法,可用于计算最大值、求和等,相比手动原子操作更高效(通常先做局部归约再合并,减少原子操作开销)。

C20未新增并行算法核心功能,但优化了执行策略的语义与实现细节,上述方案在C20中同样适用且更成熟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:45:48