并行編程——內存模型之順序一致性

1 ?定義

Sequential consistency , 簡稱 SC,定義如下

… the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequence in the order specified by its program [lamport]

下面用一個小例子說明這個定義的意思:

假設我們有兩個線程(線程1和線程2)分別運行在兩個CPU上,有兩個初始值為0的全局共享變量x和y,兩個線程分別執行下面兩條指令:

初始條件: x = y = 0;

表 1.1 ?CC 示意圖

線程 1

線程 2

x = 1;

y=1;

r1 = y;

r2 = x;

?因為多線程程序是交錯執行的,所以程序可能有如下幾種執行順序:

?表 1.2 ?CC示意圖2

Execution 1

Execution 2

Execution 3

x = 1;

r1 = y;

y = 1;

r2 = x;

結果:r1==0 and r2 == 1

y = 1;

r2 = x;

x = 1;

r1 = y;

結果: r1 == 1 and r2 == 0

x = 1;

y = 1;

r1 = y;

r2 = x;

結果: r1 == 1 and r2 == 1

Execution 1

Execution 2

Execution 3

當然上面三種情況并沒包括所有可能的執行順序,但是它們已經包括所有可能出現的結果了,所以我們只舉上面三個例子。我們注意到這個程序只可能出現上面三種結果,但是不可能出現r1==0 and r2==0的情況。

SC其實就是規定了兩件事情:
1)每個線程內部的指令都是按照程序規定的順序(program order)執行的(單個線程的視角)
2)線程執行的交錯順序可以是任意的,但是所有線程所看見的整個程序的總體執行順序都是一樣的(整個程序的視角)

第一點很容易理解,就是說線程1里面的兩條語句一定在該線程中一定是x=1先執行,r1=y后執行。第二點就是說線程1和線程2所看見的整個程序的執行順序都是一樣的,舉例子就是假設線程1看見整個程序的執行順序是我們上面例子中的Execution 1,那么線程2看見的整個程序的執行順序也是Execution 1,不能是Execution 2或者Execution 3。

有一個更形象點的例子。伸出你的雙手,掌心面向你,兩個手分別代表兩個線程,從食指到小拇指的四根手指頭分別代表每個線程要依次執行的四條指令。SC的意思就是說:
(1)對每個手來說,它的四條指令的執行順序必須是從食指執行到小拇指
(2)你兩個手的八條指令(八根手指頭)可以在滿足(1)的條件下任意交錯執行(例如可以是左1,左2,右1,右2,右3,左3,左4,右4,也可以是左1,左2,左3,左4,右1,右2,右3,右4,也可以是右1,右2,右3,左1,左2,右4,左3,左4)

其實說簡單點,SC就是我們最容易理解的那個多線程程序執行順序的模型。CC 保證的是對一個地址訪問的一致性,SC保證的是對一系列地址訪問的一致性。

2 ?幾種順序約束

順序的內存一致性模型為我們提供了一種簡單的并且直觀的程序模型。但是,這種模型實際上阻止了硬件或者編譯器對程序代碼進行的大部分優化操作。為此,人們提出了很多松弛的(relaxed)內存順序模型,給予處理器權利對內存的操作進行適當的調整。例如Alpha處理器,PowerPC處理器以及我們現在使用的x86, x64系列的處理器等等。下面是一些內存順序模型

2.1 ?TSO (整體存儲定序)

  • 數據載入間的執行順序不可改變。
  • 數據存儲間的順序不可改變。
  • 數據存儲同相關的它之前的數據載入間的順序不可改變。
  • 數據載入同其相關的它之前的數據存儲的順序可以改變。
  • 向同一個地址存儲數據具有全局性的執行順序。
  • 原子操作按順序執行。
  • 這方面的例子包括x86 TSO26和SPARC TSO.

2.2 ?PSO (部分存儲定序)

  • 數據載入間的執行順序不可改變。
  • 數據存儲間的執行順序可以改變。
  • 數據載入同數據存儲間相對順序可以改變。
  • 向同一個地址存儲數據具有全局性的執行順序。
  • 原子操作同數據存儲間的順序可以改變。
  • 這方面的例子包括SPARC PSO.

2.3 ?RMO (寬松內存定序)

  • 數據載入間的順序可以改變。
  • 數據載入同數據存儲間的順序可以改變。
  • 數據存儲間的順序可以改變。
  • 向同一個地址存儲數據具有全局性的執行順序。
  • 原子操作同數據存儲和數據載入間的順序可以改變。
  • 這方面的例子包括Power27和ARM.7

圖 1 ?一些體系架構的內存順序標準

?

圖 2 ?強內存順序模型和弱內存順序模型一些例子,

最左邊的內存順序一致性約束越弱,右邊的約束是在左邊的基礎上加上更多的約束,X86/64 算是比較強的約束。

?

3 ?亂序執行和內存屏障

任何非嚴格滿足SC規定的內存順序模型都產生所謂亂序執行問題,從編程人員的代碼,到編譯器,到CPU運行,中間可能至少需要對代碼次序做三次調整,每一次調整都是為了最終執行的性能更高。如下圖

圖 3 ?編譯亂序和運行亂序

串行時代,編譯器和CPU對代碼所進行的亂序執行的優化對程序員都是封裝好了的,無痛的,所以程序員不需要關心這些代碼在執行時被亂序成什么樣子。在單核多線程時代,mutex , semaphore 等機制在實現的時候考慮了編譯和執行的亂序問題,可以保證關鍵代碼區不會被亂序執行。在多核多線程時代,大部分情況下跟單核多線程是類似的,通過鎖調用可以保證共享區執行的順序性。但某種情況下,比如自己編寫無鎖程序,則會被暴露到這個問題面前。

?下面通過一個例子解釋亂序執行和內存屏障這兩個概念。

[來源:http://preshing.com/20120625/memory-ordering-at-compile-time]

示例代碼:

int A, B;

void foo()

{

??? A = B + 1;

??? B = 0;

}

普通編譯選項:

$ gcc -S -masm=intel foo.c

$ cat foo.s

??????? ...

??????? mov???? eax, DWORD PTR _B? (redo this at home...)

??????? add???? eax, 1

??????? mov???? DWORD PTR _A, eax

??????? mov???? DWORD PTR _B, 0

加上 -o2 優化編譯選項,可以看到,B的賦值操作順序變了

$ gcc -O2 -S -masm=intel foo.c

$ cat foo.s

??????? ...

??????? mov???? eax, DWORD PTR B

??????? mov???? DWORD PTR B, 0

??????? add???? eax, 1

??????? mov???? DWORD PTR A, eax

??????? ...

上述情況在某些場景下導致的后果是不可接受的,比如下面這段偽代碼中,生產者線程執行于一個專門的處理器之上,它先生成一條消息,然后通過更新ready的值,向執行在另外一個處理器之上的消費者線程發送信號,由于亂序執行,這段代碼在目前大部分平臺上執行是有問題的:

處理器有可能會在將數據存儲到message->value的動作執行完成之前和/或其它處理器能夠看到message->value的值之前,執行consume函數對消息進行接收或者執行將數據保存到ready的動作。

圖 4 ?亂序執行

回到之前的例子,加上一句內存屏障命令

int A, B;

?

void foo()

{

??? A = B + 1;

??? asm volatile("" ::: "memory");

??? B = 0;

}

依然采用 o2 優化編譯選項,發現這次B的賦值操作順序沒有變化

$ gcc -O2 -S -masm=intel foo.c

$ cat foo.s

??????? ...

??????? mov???? eax, DWORD PTR _B

??????? add???? eax, 1

??????? mov???? DWORD PTR _A, eax

??????? mov? ???DWORD PTR _B, 0

??????? ...

在內存順序一致性模型不夠強的多核平臺上,例子2的正確實現應該是下面這種,需要加上兩個內存屏障語句。

圖5 ?內存屏障

X86 的內存屏障 #define barrier() __asm__ __volatile__("": : :"memory")

更多X86內存屏障請參考 :?http://blog.csdn.net/cnctloveyu/article/details/5486339

?

轉載于:https://www.cnblogs.com/jiayy/p/3246157.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376490.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376490.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376490.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

160 - 4 ajj.1

環境: Windows Xp sp3 輸入Name和Serial,無錯誤提示。看說明,只有正確時才有提示 OD載入,搜索字符串,發現兩個字符串: Panel1DblClick和Panel1Click 一個雙擊一個單擊 先跟隨單擊的: 00457…

JS判斷是否安裝flash player及當前版本

function flashChecker() {var hasFlash 0;     //是否安裝了flashvar flashVersion 0;   //flash版本if(document.all) {var swf new ActiveXObject(ShockwaveFlash.ShockwaveFlash);if(swf) {hasFlash 1;VSwf swf.GetVariable("$version");flashVersion…

Daily Scrum 11.18

今日完成任務: 1.在提問問題的時候為問題創建索引 2.解決了修改個人資料后刷新沒有更新的問題 3.初步加入了采納功能(沒完善UI設計) 遇到困難:創建索引之后,跳轉到主頁,需要重新登錄,找了半天不…

160 - 5 ajj.2

環境: Windows xp sp3 打開,輸入點東西到輸入框(這里把第一個輸出框稱為text1)里面,點一下注冊,什么反應都沒有。 到處都點一點,每張圖片都點一下,還是什么反應都沒有。 查殼&…

移動平臺WEB前端開發技巧匯總

原名《移動平臺3G手機網站前端開發布局技巧匯總》,由武方博整理的,讓我們了解下移動設備上的WEB站點開發的基礎知識,多些時間和精力去優化其他細節,我這里對原文的標簽格式做了細微的調整,閱讀查看起來明晰些&#xff…

0809

來自網銷協會消息:8月8日,第八屆豫商大會新聞發布會在鄭州舉行,由河南省政協主辦,省商務廳、省工商聯、省豫商聯合會協辦,安陽市人民政府承辦的第八屆豫商大會將于8.28如期舉行。本次大會會期兩天,其中&…

160 - 6 aLoNg3x.1

環境: Windows xp sp3 查殼,這次不用脫殼了,但是還是Delphi程序。 打開后看隨便輸點東西進去,發現Nome什么都能輸入,但最多10個字符,而 Codice可以是數字或者是“$”,在輸入“$”后就可以輸入…

hyper-v 用戶無法再 創建外部配置存儲 0x80070005

windows server 2008R2 剛安裝的hyper-v 重啟過。 修改配置文件到d:\Hyper-V目錄下, hyper-V 創建 服務器遇到錯誤 操作失敗 創建外部配置存儲:一般性拒絕訪問錯誤 虛擬機ID 0x80070005 d:\hyper-V 安全權限為 everyone 所有,users 所有,admi…

160 - 7 aLoNg3x.2

環境: Windows Xp sp3 打開程序,看了幫助發現要求還是看到那個logo, 但是這次少了個按鈕,真棒! 但是這次的Codice卻是什么都可以輸入進去了。 查一下殼發現還是Delphi程序。 因為還是Delphi的程序,有了前…

Spring 中的國際化Message的簡單例子(ApplicationContext) 不跟框架集成的版本

首先&#xff0c;建立一個描述message的XML文件&#xff0c;名為messages.xml <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-bean…

簡述進程間通信方式

進程間通信方式通常有共享內存 信號量 消息隊列 管道 FIFO Socket等幾種。 共享內存的模型&#xff0c;它是最有效率的進程間通信方式進程間信號量是進程間同步主要方式&#xff0c;信號量操作為負的時候&#xff0c;進程阻塞。直到信號量為正 內存映射是一種特殊的共享內存…

輔助的寫與數據庫交互的XML文件的類

現在企業級WEB應用中與數據庫交互的XML文件都是通過插件自動生成的&#xff0c;不過有些時候修改比較老的項目的時候也是需要手動的來做這一動作的&#xff01;如下代碼就是一個實現上述的功能的輔助類&#xff0c;在此記錄一下以備后用&#xff01; package com.cn.common.uti…

160 - 8 Andrnalin.1

環境&#xff1a; Windows xp sp3 打開&#xff0c;就一個Key輸入框&#xff0c;輸入&#xff1a;goodname&#xff0c;點OK&#xff0c;彈出一個 不明文字的框&#xff0c;反正肯定不對。 查殼&#xff0c;無殼的vb程序。OD載入&#xff1a; 查找字串&#xff0c;翻到最下…

C++ 虛函數表解析

C 虛函數表解析 陳皓 http://blog.csdn.net/haoel 前言 C中的虛函數的作用主要是實現了多態的機制。關于多態&#xff0c;簡而言之就是用父類型別的指針指向其子類的實例&#xff0c;然后通過父類的指針調用實際子類的成員函數。這種技術可以讓父類的指針有“多種形態”&#x…

160 - 9 Andrnalin.2

環境&#xff1a; Windows xp sp3 打開&#xff0c;這次升級了&#xff0c;有個Name和一個Key&#xff0c;輸入&#xff1a; Name&#xff1a;goodname Key&#xff1a;12345678 肯定錯誤。拿到錯誤信息的字符串 查殼&#xff0c;無殼的VB程序。 直接OD載入&#xff0c;字…

[PALAPALA] 無題 - 外來的和尚會念經

手機, 現代人響當當的必須品, 尤其在移動App流行的大環境之下顯得更為重要. 我, 并不是一個重度依賴手機的機粉. 但我對手機的差異化敏感度很高... 安卓手機, 我不喜歡, 因為滿大街泛濫&#xff0c;折騰過多... 蘋果手機, 我不喜歡, 因為滿大街泛濫&#xff0c;bug過多..... 相…

HTTP協議 (四) 緩存

HTTP協議 (四) 緩存 閱讀目錄 緩存的概念緩存的好處Fiddler可以方便地查看緩存的header如何判斷緩存新鮮度通過最后修改時間&#xff0c;判斷緩存新鮮度與緩存相關的headerETag瀏覽器不使用緩存直接使用緩存&#xff0c;不去服務器端驗證如何設置IE不使用緩存公有緩存和私有緩存…

160 - 10 Andrénalin.3

環境&#xff1a; Windows xp sp3 打開&#xff0c;是只有一個key&#xff0c;輸入個goodname試試&#xff0c;錯誤。。。記下錯誤信息 查殼&#xff0c;無殼的VB程序。 查找字符串&#xff1a; 00402036 UNICODE "kXy^rO|*yXo*m\kMuOn*" 00402090 UNICODE &qu…

160 - 11 Andrnalin.4

環境&#xff1a; Windows xp sp3 打開&#xff0c;這次的界面炫酷多了&#xff0c;就像輸保險箱密碼。 旁邊一個“UNREGISTRIERT”表示還沒注冊 輸入個666666&#xff0c;沒反應又沒有確認按鈕&#xff0c;可以猜測是用timer來檢測輸入的正確性 查殼&#xff0c;無殼的VB程…

ZooKeeper啟動過程2:FastLeaderElection

前一篇文章中說到&#xff0c;啟動ZooKeeper集群時&#xff0c;需要分別啟動集群中的各個節點&#xff0c;各節點以QuorumPeer的形式啟動&#xff0c;最后到達startLeaderElection和lookForLeader。 先說startLeaderElection 首先&#xff0c;初始化節點自身的currentVote【當前…