为什么std :: atomic <bool>比volatile bool慢得多?

34 c++ performance multithreading atomic c++11

多年来我一直在使用volatile bool进行线程执行控制,它工作正常

// in my class declaration
volatile bool stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}
Run Code Online (Sandbox Code Playgroud)

现在,由于c ++ 11增加了对原子操作的支持,我决定尝试这样做

// in my class declaration
std::atomic<bool> stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}
Run Code Online (Sandbox Code Playgroud)

但它比它快几个数量级volatile bool!

我编写的简单测试用例大约需要1秒才能完成volatile bool.随着std::atomic<bool>不过,我一直在等待约10分钟,并放弃了!

我试着用memory_order_relaxed旗帜loadstore同样的效果.

我的平台:Windows 7 64位MinGW gcc 4.6.x

我做错了什么?

UPD

是的,我知道volatile不会使变量线程安全.我的问题不是关于挥发性的,而是关于为什么原子是非常慢的.

UPD2 @all,感谢您的评论 - 我今晚到达机器后会尝试所有建议.

KoK*_*oru 31

代码来自"Olaf Dietsche"

 USE ATOMIC
 real   0m1.958s
 user   0m1.957s
 sys    0m0.000s

 USE VOLATILE
 real   0m1.966s
 user   0m1.953s
 sys    0m0.010s
Run Code Online (Sandbox Code Playgroud)

如果您使用的是GCC SMALLER 4.7

http://gcc.gnu.org/gcc-4.7/changes.html

添加了对指定C++ 11/C11内存模型的原子操作的支持.这些新的__atomic例程替换了现有的__sync内置例程.

内存块也可以使用原子支持.如果内存块的大小和对齐方式与支持的整数类型相同,则将使用无锁指令.没有无锁支持的原子操作留作函数调用.GCC原子维基上的"外部原子库"部分提供了一组库函数.

所以是啊..唯一的解决方案是升级到GCC 4.7

  • 那么,你的原子不是"无锁"mingw + windows可能是问题所在.它适用于g ++(4.7)+ linx.只要你的基准吧!如果不做"anti_optimization"之类的操作,那么带有volatile的循环将不会与"-O3"一起存在 (2认同)

Ola*_*che 12

由于我对此感到好奇,我自己在Ubuntu 12.04,AMD 2.3 GHz,gcc 4.6.3上进行了测试.

#if 1
#include <atomic>
std::atomic<bool> stop_(false);
#else
volatile bool stop_ = false;
#endif

int main(int argc, char **argv)
{
    long n = 1000000000;
    while (!stop_) {
        if (--n < 0)
            stop_ = true;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译 g++ -g -std=c++0x -O3 a.cpp

虽然和@aleguna的结论相同:

  • 只是bool:

    实际0m0.004s
    用户0m0.000s
    sys 0m0.004s

  • volatile bool:

    $ time ./a.out
    real 0m1.413s
    user 0m1.368s
    sys 0m0.008s

  • std::atomic<bool>:

    $ time ./a.out
    real 0m32.550s
    user 0m32.466s
    sys 0m0.008s

  • std::atomic<int>:

    $ time ./a.out
    real 0m32.091s
    user 0m31.958s
    sys 0m0.012s

  • gcc 4.6原子不是无锁的.升级到gcc 4.7+ (6认同)