У меня есть 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-битной переменной?
если я объявлю 64-битные значения как атомарные и начну читать с использованием ослабленного барьера памяти, будет ли он иметь такую же цену производительности, что и чтение неатомической 64-битной переменной?
Да, они имеют одинаковую стоимость с точки зрения барьеров / ограждений памяти.
В x86_64 каждая загрузка имеет семантическую структуру aqcuire, поэтому нагрузка с семантикой acqu аналогична загрузке с расслабленной семантикой с точки зрения процессора. Но они отличаются с точки зрения компилятора (расслабленные операции могут быть переупорядочены с другими).