【问题标题】:Does .load(std::memory_order_relaxed) cost same as reading unatomic variable?.load(std::memory_order_relaxed) 与读取非原子变量的成本相同吗?
【发布时间】:2015-07-03 22:46:06
【问题描述】:

我有 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 位变量具有相同的性能成本?强>

【问题讨论】:

  • x86 处理器使用相当强的内存排序。我相信正常的加载和存储具有获取和释放语义,因此不需要围栏或其他特殊指令。其他 CPU 可能完全不同。特别是,有些人可能必须使用多条指令来读取 64 位值(例如 32 位 CPU),因此需要额外的同步指令才能以原子方式读取它。
  • 这个问题很困惑。没有“宽松的记忆屏障”这样的东西。 C++ 定义了原子操作上的内存排序,它特定于一个内存位置,以及单独(几乎无用)的内存栅栏,你永远不会使用也不应该使用。

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


【解决方案1】:

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

是的,它们在内存屏障/栅栏方面的成本相同。

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

【讨论】:

  • 您好,感谢您的回答!你提到商店,负载呢? (因为我的问题与“读取”64位有关)。谢谢:)
  • @user997112,除了加载(存储它以供在表达式中使用、更改它,甚至只是增加它)之外的任何东西——没有别的是原子的!对您有意保持无锁状态的数据要非常小心。
  • 这个答案不一定适用于 RISC 64b 架构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 2018-05-20
  • 1970-01-01
  • 2023-03-23
  • 2015-09-16
  • 1970-01-01
  • 2011-02-13
相关资源
最近更新 更多