.load(std :: memory_order_relaxed)与读取非原子变量的成本相同吗?

时间:2015-07-03 22:46:06

标签: c++ multithreading assembly atomic memory-barriers

我有64位,我需要在事件发生之前非常快速地读取,然后在事件执行比较和交换之后。

我以为我可以在事件发生之前加载(std::memory_order_relaxed)以便快速阅读,然后在事件发生后使用常规比较和交换。

当我比较非原子64位读取,原子(放松)和原子(获取)之间的组件时,我看不出组件中的任何差异。这是C ++测试:

int main(){
    volatile uint64_t var2;
    std::atomic<uint64_t> var;  // The variable I wish to read quickly
    var = 10;

    var2 = var.load(std::memory_order_relaxed);
    //var2 = var; // when var is not atomic
    //var2 = var.load(std::memory_order_acquire);  To see if the x86 changed 
}

给这个集会:

!int main(){
main()+0: sub    $0x48,%rsp
main()+4: callq  0x100401180 <__main>
!    volatile uint64_t var2;
!    volatile std::atomic<uint64_t> var;
!    var = 10;
!    
!    
!    var2 = var.load(std::memory_order_acquire);
main()()
main()+26: mov    %rax,0x38(%rsp)
!    
!    int x;
!    std::cin >> x;
main()+31: lea    0x2c(%rsp),%rdx
main()+36: mov    0x1f45(%rip),%rcx        # 0x100403050 <__fu0__ZSt3cin>
main()+43: callq  0x100401160 <_ZNSirsERi>
!}main()+48: mov    $0x0,%eax
main()+53: add    $0x48,%rsp
main()+57: retq  

显然使用std::memory_order_acquire的程序集应该与非原子变量读取不同?

这是因为读取64位是原子的,只要数据是对齐的,因此汇编没有区别?我原本以为使用更强大的内存屏障会插入围栏指令还是什么?

我想知道的真正问题是,如果我将64位声明为原子并且使用宽松的内存屏障进行读取,它是否会具有与读取非原子64位变量相同的性能成本?

1 个答案:

答案 0 :(得分:0)

  

如果我将64位声明为原子并且使用宽松的内存屏障读取,它是否会与读取非原子64位变量具有相同的性能成本?

是的,他们在内存障碍/围栏方面的成本相同。

在x86_64上,每个加载都具有一定的语义,因此从处理器的角度来看,具有获取语义的加载与具有宽松语义的加载相同。但它们与编译器的观点不同(宽松的操作可以与其他人重新排序)。