首先,必須介紹超級好站 : http://preshing.com/

還有這個:http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

 

memory_order_acquire : 保證其下面的 load 一定不會在其前面執行 !!

memory_order_release: 保證其上面的 store 不會拖到其後面才執行 !!

memory_order_acq_rel: 保證上面兩個

memory_order_consume: 相關變數間的保證順序 , 例如指標 , weak memory model 的 cpu ,

執行指令不像 strong memory model like intel,AMD 那麼嚴格 , 連指標內容更改後再  derefrence

都可能改變執行順序

memory_order_relaxed : do whatever order it like to do !!

 

Intel cpu 是我最常用的硬體 , 它是 TSO 架構 , Total Store Ordering , 其保證 :

1. store / store ordering

2. load / load ordering

3. load / store ordering

唯一不保證 : store/load ordering

store/load 最有名的例子 : (x=0;y=0; initially)

Thread1 : x=1 ;  r1= y ;

Thread2 : y =1 ; r2 =x ;

假如 Thread1 先 load y 才執行 store x =1 ; 而且 Thread2 先執行 load x 才執行 store y = 1 ;

那麼這兩個 threads 執行完後 , 有可能出現 r1=0 ; r2 = 0 ; 

Intel 都可能出現這個結果, 更別說其他 weak memory model 的 cpu ,

Intel cpu 每個 core 都有一個 store Buffer , 當執行  x = 1 ; 時 ,如果 x 變數所在的 cache line 不在它的 cache,

此時會將 x = 1 寫到 store buffer , 再往下執行,...First In First Out 的 store buffer 就是它 store/store gurantee 的原因,

此時, 如果 y變數 cache line 在它的 cache , 此時 load y 再 store to r1 , 寫入  store buffer , 這時  ,

單這個 core 看到的,就是 x=1;r1=0; ....所以,你應該可以看出來, r1=0 and r2=0 是怎樣出現的 !!

 

假設 Thread1 執行以下程式 :

x=1;

y=1;

z=1;

 

Thread2 :

if(z==1)

{

    x==1 ?

    y==1 ?

}

 

如果是 intel , AMD,  x ==1 and y==1 一定成立, 因為 store/store , load/load ordering 的關係 ,

其他 weak memory model cpu 不一定 , 因為 z=1 不一定比 x=1 後執行,

load 順序也可以跳著來 !!!!!

 

c++11 用 atomic 以及 ordering 來處理此狀況,如以下 :

Thread1 :

x.store(1,memory_order_relaxed) ;

y.store(1,memory_order_relaxed) ;

z.store(1,memory_order_release) ;

Thread2 :

if(z.load(memory_order_acquire)==1)

{

    x.load(memory_order_relaxed)==1 ?

    y.load(memory_order_relaxed)==1 ?

}

 

 

 

全站熱搜

hedgezzz 發表在 痞客邦 留言(0) 人氣()