2015-04-28 21 views
5

Bu https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html, sayılı belgeye göre, piyasaya sürülen bir depo MOV (belleğe) olarak uygulanmaktadır. onun http://en.cppreference.com/w/cpp/atomic/memory_orderMOV x86 komutu C++ 11 memory_order_release atomik deposunu uyguluyor mu?

memory_order_release göre

:

bu hafıza düzenine sahip bir kaydetme işlemi salma işlemi gerçekleştirir: bir hafıza Bu depo edilmesinden sonra yeniden sıralanmış olabilir mevcut iplik erişir. Bu, geçerli parçacığındaki tüm yazımların, diğer atomlarda atomik değişkenini veya atomik değişkeni aynı atomik tüketen atomik değişkeni görünür hale getiren diğer atomik değişkenler olarak görünür olmasını sağlar.

Ben memory_order_release kullanıldığında, daha önce yapılan tüm bellek saklar bu daha önce bitirmek gerektiğini anlıyoruz.

int a; 
a = 10; 
std::atomic<int> b; 
b.store(50, std::memory_order_release); // i can be sure that 'a' is already 10, so processor can't reorder the stores to 'a' and 'b' 

SORU: nasıl sadece MOV komutu bu davranış için yeterli olması mümkün mü? MOV, işlemciye önceki tüm mağazaları bitirmesini nasıl söyler?

en azından gördüğüm Intel derleyicisi ile derlenen kod, haritalama gibi görünmektedir
+1

"x86" üzerinde – Cubbi

+0

@ cubbi: un, önemli, – Krab

+0

bitti: Dinamik bir programlanmış ISA olduğundan, çip her zaman en kötü durumda olduğunu varsayar. – user3528438

cevap

3

: kodu için

0000000000401100 <_Z5storeRSt6atomicIiE>: 
    401100:  48 89 fa    mov %rdi,%rdx 
    401103:  b8 32 00 00 00   mov $0x32,%eax 
    401108:  89 02     mov %eax,(%rdx) 
    40110a:  c3      retq 
    40110b:  0f 1f 44 00 00   nopl 0x0(%rax,%rax,1) 

0000000000401110 <_Z4loadRSt6atomicIiE>: 
    401110:  48 89 f8    mov %rdi,%rax 
    401113:  8b 00     mov (%rax),%eax 
    401115:  c3      retq 
    401116:  0f 1f 00    nopl (%rax) 
    401119:  0f 1f 80 00 00 00 00 nopl 0x0(%rax) 

:

#include <atomic> 
#include <stdio.h> 

void store(std::atomic<int> & b) ; 

int load(std::atomic<int> & b) ; 

int main() 
{ 
    std::atomic<int> b ; 

    store(b) ; 

    printf("%d\n", load(b)) ; 

    return 0 ; 
} 

void store(std::atomic<int> & b) 
{ 
    b.store(50, std::memory_order_release) ; 
} 

int load(std::atomic<int> & b) 
{ 
    int v = b.load(std::memory_order_acquire) ; 

    return v ; 
} 

akım Intel architecture documents, Cilt 3 (Sistem Programlama Rehberi), bunu açıklayan iyi bir iş yapar. Bkz: P6

8.2.2 Bellek Sipariş ve Daha Fazla Son İşlemci Aileleri

  • diğer okur ile yeniden sıralanmış değil Okur.
  • Daha eski okumalarla yazılanlar yeniden düzenlenmez.
  • aşağıdaki istisnalarla, diğer yazma ile yeniden sıralanmış değil belleğe yazar: ...

tam bellek modeli yoktur açıklanmıştır. Intel ve C++ standart milletlerinin, Hacim 3'te açıklanan bellek modeline uygun olarak mümkün olan her bir bellek siparişi işleminin en iyi eşlemesini azaltmak için birlikte çalıştıklarını ve düz depolar ve yüklerin belirlendiğini varsayalım. bu durumlarda yeterli olmak.

Sadece x86-64 üzerindeki bu sipariş edilen mağaza için özel bir talimat gerekmediğinden, bunun evrensel olarak doğru olacağı anlamına gelmez. Powerpc için mağaza ile birlikte bir lwsync komutu gibi bir şey görmeyi beklerim ve hpux (ia64) üzerinde derleyici bir st4.rel komutu kullanmalıdır.

4

Çalışma zamanında bir bellek siparişi var (CPU tarafından yapıldı) ve derleme zamanında bir bellek siparişi var. memory_order_release, derleyicinin verilere erişimi yeniden sıralamasını önler.Daha fazla bilgi için lütfen this article (ve ayrıca bu blogda diğer pek çok iyi olanı okuyun) okuyun.