2014-11-23 13 views
5

x ++ üzerinde C++ 11 bellek modelinin rahat sipariş semantikini test ediyordum ve x86/64 üzerinde sadece mağaza/yük yeniden sıralama var diye söylendi. rahat siparişi test etmek için program.C++ 11 bellek modelinin rahat siparişi

İdeal olarak, eğer yeniden sıralama mevcutsa (ki bunu yaparsa), programım "g_a == g_b == 0" alma durumuna düşmelidir, ancak bunu uzun bir süre test ettim ve beklenen sonuçları asla alamıyorum. nedenini açıklayan kimse olabilir mi? Teşekkürler.

[güncelleme] Ben g ++ Linux x86/64 4.8.3 ile derlenmiş aşağıdaki kod çalışmaz, kullanılan derleyici söz unutmak için

üzgün. @ Mat'ın hatırlatıcısı sayesinde, ben clang ++ 3.4.2 kullanarak derlemeyi deneyin, bu sefer yeniden sıralama gördüm, bu yüzden g ++ bir hata olabilir.

#include <iostream> 
#include <thread> 
#include <atomic> 

using namespace std; 
atomic<int> g_a, g_b; 
atomic<int> g_x, g_y; 
memory_order order = memory_order_relaxed; 

void bar1() 
{ 
    register int t = 0; 
    g_x.store(42, order); 
    t = g_y.load(order); 
    g_a = t; 
} 

void bar2() 
{ 
    register int t = 0; 
    g_y.store(24, order); 
    t = g_x.load(order); 
    g_b = t; 
} 

int main() 
{ 
    for (int i = 0; i < 1000000; ++i) 
    { 
     g_a = 0; g_b = 0; 
     g_x = 0; g_y =0; 
     thread t1(&bar1); 
     thread t2(&bar2); 

     t1.join(); 
     t2.join(); 
     if (g_a.load(order) == 0 && g_b.load(order) == 0) 
     { 
      cout << "g_a == g_b == 0" << endl; 
     } 
    } 
} 
+2

Kodunuza bakmadım, ancak x86'nın ihtiyacınız olabileceğinden daha güçlü garantiler sağladığını bilmelisiniz. – Mehrdad

+0

Bunun farkındayım ve bu yüzden emin olmak için bildiğim test için "mağaza/yük" yeniden sıralama türünü seçiyorum. – kmalloc

+1

FWIW, Linux/x86_64 üzerinde clang ++ 3.5 (libstdC++ 4.7.3 kullanarak '' -O3 -std = C++ 11 -pthread ') ile çalışırken "beklenen" sonuçlarınızı görüyorum. Bunu GCC 4.9.2 ile görmüyorum. LibC++ kullanarak clang ++ ile görmüyorum. – Mat

cevap

3

Doğru bellek bariyeri ile derleme üretebilmek için, derleme zamanında C++ sipariş parametrelerinin bilinmesi gerekir.

Dump of assembler code for function bar1(): 
    0x0000000000400fc0 <+0>:  movl $0x2a,0x20128a(%rip)  # 0x602254 <g_x> 
    0x0000000000400fca <+10>: mfence 
    0x0000000000400fcd <+13>: mov 0x20127d(%rip),%eax  # 0x602250 <g_y> 

Eğer değiştirirseniz:

memory_order order = memory_order_relaxed; 

Bu sabit bir derleme zamanı değil, bu nedenle gccmemory_order_seq_cst varsayalım ve bir mfence talimat eklemek için gidiyor:

sorun şu ifadesinde yatmaktadır bunu yapmak için:

rahat parametre yürürlüğe girecek ve mfence gitti:

Dump of assembler code for function bar1(): 
    0x0000000000400fc0 <+0>:  movl $0x2a,0x201286(%rip)  # 0x602250 <g_x> 
    0x0000000000400fca <+10>: mov 0x20127c(%rip),%eax  # 0x60224c <g_y> 

Eğer -O3 optimizasyonu ile derlemek, şimdi yeniden sipariş gösterecektir ikili çalışan.

+0

vay, bu mantıklı. Teşekkürler. Belki de derleyici bazı uyarılar vermelidir. – kmalloc

+0

Evet, bu ideal olurdu. Dil kuralını ihlal etmediğinizden emin olabilirsiniz. – LWimsey