简体   繁体   English

std :: atomic上的加法 <double> 不加和非原子的对应物

[英]addition on std::atomic<double> not adding up to non-atomic counterpart

I am trying to perform an addition on a double atomically in a loop using a compare and exchange scheme with this function: 我正在尝试使用此功能的比较和交换方案在循环中以原子方式对双精度执行加法运算:

namespace my
{
    template<typename value_type>
    value_type atomic_add(std::atomic<value_type>& operand, value_type value_to_add)
    {
        value_type old = operand.load(std::memory_order_consume);
        value_type desired = old + value_to_add;
        while (!operand.compare_exchange_weak(old, desired, std::memory_order_release, std::memory_order_consume))
            desired = old + value_to_add;

        return desired;
    }
}

This is used in my code like so: 这在我的代码中使用如下:

[ size of containers = 62, scalar = 318.0, values in containers between 0.0 and 55.0, all values are of type double ]

for(size_t i = 0; i < container.size(); i++)
{
    my::atomic_add<double>(Q, container2[i] - std::pow(container3[i], 2) / scalar);
}

The output is 0.57784502195324539 . 输出为0.57784502195324539

However, replacing all my_atomic with the += operator, and replace all std::atomic<double> with double gives 0.52something , which is closer to what I was expecting. 但是,用+=运算符替换所有my_atomic,并将所有std::atomic<double>替换为double得到0.52something ,这与我的预期更加接近。

Any idea why this is happening? 知道为什么会这样吗?

Thank you. 谢谢。

I seem to have fixed this issue so I am going to post an answer as a cautionary tale for other developers. 我似乎已经解决了这个问题,所以我将发布一个答案作为对其他开发人员的警告。

Here is a minimal working example: 这是一个最小的工作示例:

#include <iostream>

#include <atomic>
#include <vector>

namespace my
{
    template<typename value_type>
    value_type atomic_add(std::atomic<value_type>& operand, value_type value_to_add)
    {
        value_type old = operand.load(std::memory_order_consume);
        value_type desired = old + value_to_add;
        while (!operand.compare_exchange_weak(old, desired, std::memory_order_release, std::memory_order_consume))
            desired = old + value_to_add;

        return desired;
    }
}

int main()
{
    std::vector<double> vector;

    for(int i = 0; i < 100; i++)
    {
        double a;
        a = 2.0;
        vector.push_back(a);
    }

    std::atomic<double> d;

    for(int i = 0; i < vector.size(); i++)
        my::atomic_add(d, vector[i]);

    std::cout << d << std::endl;
}

The output of which is 202 . 输出是202 It appears that d is initialized to 2.0 . 看来d初始化为2.0 The moral of this story is to always make sure that your std::atomic s are initialized to a sane value. 这个故事的寓意是始终确保将std::atomic初始化为合理的值。

Furthermore, other answers have pointed out that it is generally a bad idea to store std::atomics s in a vector as they are not CopyAssignable and CopyConstructible . 此外,其他答案指出,将std::atomics存储在向量中通常是一个坏主意,因为它们不是CopyAssignableCopyConstructible

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM