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

时间:2012-10-30 09:15:42

标签: c++ multithreading performance c++11 atomic

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

// in my class declaration
volatile bool stop_;

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

// In the thread function
while (!stop_)
{
     do_things();
}

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

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

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

// In the thread function
while (!stop_)
{
     do_things();
}

但它比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,谢谢你的评论 - 我今晚到达机器后会尝试所有的建议。

3 个答案:

答案 0 :(得分:30)

“Olaf Dietsche”的代码

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

 USE VOLATILE
 real   0m1.966s
 user   0m1.953s
 sys    0m0.010s

如果您使用的是GCC SMALLER 4.7

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

  

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

     

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

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

答案 1 :(得分: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;
}

使用g++ -g -std=c++0x -O3 a.cpp

编译

虽然和@aleguna的结论相同:

  • 只是bool

      

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

  • volatile bool

      

    $ time ./a.out
      真正的0m1.413s
      用户0m1.368s
      sys 0m0.008s

  • std::atomic<bool>

      

    $ time ./a.out
      真正的0m32.550s
      用户0m32.466s
      sys 0m0.008s

  • std::atomic<int>

      

    $ time ./a.out
      真正的0m32.091s
      用户0m31.958s
      sys 0m0.012s

答案 2 :(得分:2)

我的猜测是这是一个硬件问题。 当你编写volatile时,你告诉编译器不要假设有关变量的任何内容,但据我所知,硬件仍将它视为普通变量。这意味着变量将始终在缓存中。 当您使用原子时,您使用特殊的硬件指令,这可能意味着每次使用变量都是从主存储器中取出的。 时间上的差异与此解释一致。