gpu編譯技術
㈠ 關於GPU的問題!
目錄:
第一章:第二代及以後的GPU工作流程簡介
第二章:DirectX8和DirectX9 GPU的傳統流水線
第三章:頂點和像素操作指令
第四章:傳統GPU指令的執行
第五章:統一渲染架構
第六章:G80和R600的統一渲染架構實現
第七章:G80與R600效能對比
第八章:尷尬的中端--Geforce8600簡析
前面4章 我將先簡要介紹下DirectX8/9顯卡的核心----圖形處理單元GPU的工作流程和指令處理情況
從第5章開始討論統一渲染架構、新一代DirectX10 GPU的特性,G80/Geforce8800與R600/RadeonHD2900XT的架構具體實現及其區別。最後將會對中端最受關注的Geforce8600進行相應的簡單分析。
第一章:第二代及以後的GPU工作流程簡介
簡單(而不一定絕對科學)的說:GPU主要完成對3D圖形的處理--圖形的生成渲染。
GPU的圖形(處理)流水線完成如下的工作:(並不一定是按照如下順序)
頂點處理:這階段GPU讀取描述3D圖形外觀的頂點數據並根據頂點數據確定3D圖形的形狀及位置關系,建立起3D圖形的骨架。在支持DX8和DX9規格的GPU中,這些工作由硬體實現的Vertex Shader(定點著色器)完成。
光柵化計算:顯示器實際顯示的圖像是由像素組成的,我們需要將上面生成的圖形上的點和線通過一定的演算法轉換到相應的像素點。把一個矢量圖形轉換為一系列像素點的過程就稱為光柵化。例如,一條數學表示的斜線段,最終被轉化成階梯狀的連續像素點。
紋理帖圖:頂點單元生成的多邊形只構成了3D物體的輪廓,而紋理映射(texture mapping)工作完成對多變形表面的帖圖,通俗的說,就是將多邊形的表面貼上相應的圖片,從而生成「真實」的圖形。TMU(Texture mapping unit)即是用來完成此項工作。
像素處理:這階段(在對每個像素進行光柵化處理期間)GPU完成對像素的計算和處理,從而確定每個像素的最終屬性。在支持DX8和DX9規格的GPU中,這些工作由硬體實現的Pixel Shader(像素著色器)完成。
最終輸出:由ROP(光柵化引擎)最終完成像素的輸出,1幀渲染完畢後,被送到顯存幀緩沖區。
總結:GPU的工作通俗的來說就是完成3D圖形的生成,將圖形映射到相應的像素點上,對每個像素進行計算確定最終顏色並完成輸出。
第二章:DirectX8和DirectX9 GPU的傳統流水線
前面的工作流程其實已經說明了問題。本章來總結一下,承前啟後。
傳統的GPU功能部件我們不妨將其分為頂點單元和像素流水線兩部分。
頂點單元由數個硬體實現的Vertex Shader組成。
傳統的像素流水線由幾組PSU(Pixel Shader Unit)+TMU+ROP組成。
於是,傳統的GPU由頂點單元生成多邊形,並由像素流水線負責像素渲染和輸出。
對於像素流水線需要做的說明是:雖然傳統的流水線被認為=1PSU+1TMU+1ROP,但這個比例不是恆定的,例如在RadeonX1000(不包括X1800)系列中被廣為稱道的3:1黃金架構,PSU:TMU:ROP的數量為3:1:1。一塊典型的X1900顯卡具有48個PSU,16個TMU和16個ROP。之所以採用這種設計方法,主要考慮到在當今的游戲中,像素指令數要遠遠大於紋理指令的數量。ATI憑借這個優秀的架構,成功擊敗了Geforce7,在DX9後期取得了3D效能上的領先。
總結:傳統的GPU由頂點單元生成多邊形,像素流水線渲染像素並輸出,一條像素流水線包含PSU,TMU,和ROP(有的資料中不包含ROP),比例通常為1:1:1,但不固定。
第三章:頂點和像素操作指令
GPU通過執行相應的指令來完成對頂點和像素的操作。
熟悉OpenGL或Direct3D編程的人應該知道,像素通常使用RGB三原色和alpha值共4個通道(屬性)來描述。而對於頂點,也通常使用XYZ和W 4個通道(屬性)來描述。因而,通常執行一條頂點和像素指令需要完成4次計算,我們這里成這種指令為4D矢量指令(4維)。當然,並不是所有的指令都是4D指令,在實際處理中,還會出現大量的1D標量指令以及2D,3D指令。
總結:由於定點和像素通常用4元組表示屬性,因而頂點和像素操作通常是4D矢量操作,但也存在標量操作。
第四章:傳統GPU指令的執行
傳統的GPU基於SIMD的架構。SIMD即Single Instruction Multiple Data,單指令多數據。
其實這很好理解,傳統的VS和PS中的ALU(算術邏輯單元,通常每個VS或PS中都會有一個ALU,但這不是一定的,例如G70和R5XX有兩個)都能夠在一個周期內(即同時)完成對矢量4個通道的運算。比如執行一條4D指令,PS或VS中的ALU對指令對應定點和像素的4個屬性數據都進行了相應的計算。這便是SIMD的由來。這種ALU我們暫且稱它為4D ALU。
需要注意的是,4D SIMD架構雖然很適合處理4D指令,但遇到1D指令的時候效率便會降為原來的1/4。此時ALU 3/4的資源都被閑置。為了提高PS VS執行1D 2D 3D指令時的資源利用率,DirectX9時代的GPU通常採用1D+3D或2D+2D ALU。這便是Co-issue技術。這種ALU對4D指令的計算時仍然效能與傳統的ALU相同,但當遇到1D 2D 3D指令時效率則會高不少,例如如下指令:
ADD R0.xyz , R0,R1 //此指令是將R0,R1矢量的x,y,z值相加 結果賦值給R0
ADD R3.x , R2,R3 //此指令是將R2 R3矢量的w值相加 結果賦值給R3
對於傳統的4D ALU,顯然需要兩個周期才能完成,第一個周期ALU利用率75% ,第二個周期利用率25%。而對於1D+3D的ALU,這兩條指令可以融合為一條4D指令,因而只需要一個周期便可以完成,ALU利用率100%。
但當然,即使採用co-issue,ALU利用率也不可能總達到100%,這涉及到指令並行的相關性等問題,而且,更直觀的,上述兩條指令顯然不能被2D+2D ALU一周期完成,而且同樣,兩條2D指令也不能被1D+3D ALU一周期完成。傳統GPU在對非4D指令的處理顯然不是很靈活。
總結:傳統的GPU中定點和像素處理分別由VS和PS來完成,每個VS PS單元中通常有一個4D ALU,可以在一個周期完成4D矢量操作,但這種ALU對1D 2D 3D操作效率低下,為了彌補,DX9顯卡中ALU常被設置為1D+3D 2D+2D等形式。
第五章:統一渲染架構
相對於DirectX 9來說,最新的DirectX 10最大的改進在於提出了統一渲染架構,即Unified Shader。
傳統的顯卡GPU一直採用分離式架構,頂點處理和像素處理分別由Vertex Shader和Pixel Shader來完成,於是,當GPU核心設計完成時,PS和VS的數量便確定下來了。但是不同的游戲對於兩者處理量需求是不同的,這種固定比例的PS VS設計顯然不夠靈活,為了解決這個問題,DirectX10規范中提出了了統一渲染架構。
不論是頂點數據還是像素數據,他們在計算上都有很多共同點,例如通常情況下,他們都是4D矢量,而且在ALU中的計算都是沒有分別的浮點運算。這些為統一渲染的實現提供了可能。
在統一渲染架構中,PS單元和VS單元都被通用的US單元所取代,nVidia的實現中稱其為streaming processer,即流處理器,這種US單元既可以處理頂點數據,又可以處理像素數據,因而GPU可以根據實際處理需求進行靈活的分配,這樣便有效避免了傳統分離式架構中VS和PS工作量不均的情況。
總結:統一渲染架構使用US(通常為SP)單元取代了傳統的固定數目的VS和PS單元,US既可以完成頂點操作,又可以完成像素操作,因而可以根據游戲需要靈活分配,從而提高了資源利用率。
第六章:G80和R600的統一渲染架構實現
以下我們著重討論G80和R600的統一著色單元而不考慮紋理單元,ROP等因素。
G80 GPU中安排了16組共128個統一標量著色器,被叫做stream processors,後面我們將其簡稱為SP。每個SP都包含有一個全功能的1D ALU。該ALU可以在一周期內完成乘加操作(MADD)。
也許有人已經注意到了,在前面傳統GPU中VS和PS的ALU都是4D的,但在這里,每個SP中的ALU都是1D標量ALU。沒錯,這就是很多資料中提及的MIMD(多指令多數據)架構,G80走的是徹底的標量化路線,將ALU拆分為了最基本的1D 標量ALU,並實現了128個1D標量SP,於是,傳統GPU中一個周期完成的4D矢量操作,在這種標量SP中需4個周期才能完成,或者說,1個4D操作需要4個SP並行處理完成。
這種實現的最大好處是靈活,不論是1D,2D,3D,4D指令,G80得便宜其全部將其拆成1D指令來處理。指令其實與矢量運算拆分一樣。
例如一個4D矢量指令 ADD R0.xyzw , R0,R1 R0與R1矢量相加,結果賦R0
G80的編譯器會將其拆分為4個1D標量運算指令並將其分派給4個SP:
ADD R0.x , R0,R1
ADD R0.y , R0,R1
ADD R0.z , R0,R1
ADD R0.w, R0,R1
綜上:G80的架構可以用128X1D來描述。
R600的實現方式則與G80有很大的不同,它仍然採用SIMD架構。
在R600的核心裡,共設計了4組共64個流處理器,但每個處理器中擁有1個5D ALU,其實更加准確地說,應該是5個1D ALU。因為每個流處理器中的ALU可以任意以1+1+1+1+1或1+4或2+3等方式搭配(以往的GPU往往只能是1D+3D或2D+2D)。ATI將這些ALU稱作streaming processing unit,因而,ATI宣稱R600擁有320個SPU。
我們考慮R600的每個流處理器,它每個周期只能執行一條指令,但是流處理器中卻擁有5個1D ALU。ATI為了提高ALU利用率,採用了VLIW體系(Very Large Instruction Word)設計。將多個短指令合並成為一組長的指令交給流處理器去執行。例如,R600可以5條1D指令合並為一組5DVLIW指令。
對於下述指令:
ADD R0.xyz , R0,R1 //3D
ADD R4.x , R4,R5 //1D
ADD R2.x , R2,R3 //1D
R600也可以將其集成為一條VLIW指令在一個周期完成。
綜上:R600的架構可以用64X5D的方式來描述。
總結:G80將操作徹底標量化,內置128個1D標量SP,每個SP中有一個1D ALU,每周期處理一個1D操作,對於4D矢量操作,則將其拆分為4個1D標量操作。
R600仍採用SIMD架構,擁有64個SP,每個SP中有5個1D ALU,因而通常聲稱R600有320個PSU,
每個SP只能處理一條指令,ATI採用VLIW體系將短指令集成為長的VLIW指令來提高資源利用率,例如5條1D標量指令可以被集成為一條VLIW指令送入SP中在一個周期完成。
第七章:G80與R600效能對比
從前一章的討論可以看出,R600的ALU規模64X5D=320明顯比G80的128X1D=128要大,但是為何在實際的測試中,基於R600的RadeonHD2900XT並沒有取得對G80/Geforce8800GTX的性能優勢?本章將試圖從兩者流處理器設計差別上來尋找答案,對於紋理單元,ROP,顯存帶寬則不做重點討論。事實上,R600的顯存帶寬也要大於G80。
我們將從頻率和執行效能兩個方面來說明問題:
1、頻率:G80隻擁有128個1D流處理器,在規模上處於絕對劣勢,於是nVidia採用了shader頻率與核心頻率非同步的方式來提高性能。Geforce8800GTX雖然核心頻率只有575MHZ,但shader頻率卻高達1375MHZ,即SP工作頻率為核心頻率的兩倍以上,而R600則相對保守地採用了shader和核心同步的方式,在RadeonHD2900XT中,兩者均為740MHZ。這樣一來,G80的shader頻率幾乎是R600的兩倍,於是就相當於同頻率下G80的SP數加倍達到256個,與R600的320個接近了很多。在處理乘加(MADD)指令的時候,740MHZ的R600的理論峰值浮點運算速度為:740MHZ*64*5*2=473.6GFLOPS 而shader頻率為1350MHZ的G80的浮點運算速度為:1350MHZ*128*1*2=345.6GFLOPS,兩者的差距並不像SP規模差距那麼大。
2、執行效能:G80雖說shader頻率很高,但由於數量差距懸殊,即使非同步也無法補回理論運算速率的差距。於是,要尋找答案,還要從兩者流處理器的具體設計著手。
在G80中,每個矢量操作都會被拆分為1D標量操作來分配給不同的SP來處理,如果不考慮指令並行性等問題,G80在任何時刻,所有SP都是充分利用的。而R600則沒這么幸運,因為每個流處理器只能同時處理一條指令,因而R600要將短指令合並為能充分利用SP內5DALU運算資源的VLIW指令,但是這種合並並不是總能成功。目前沒有資料表明R600可以將指令拆開重組,也就是說,R600不能每時每刻都找到合適的指令拼接為5D指令來滿載他的5D SP,這樣的話我們假設處理純4D指令的情況,不能拆分重組的話,R600每個SP只能處理一條4D指令,利用率80%,而對於G80,將指令拆開成1D操作,無論何時都能100%利用。而且,R600的結構對編譯器的要求很高,編譯器必須盡可能尋找Shader指令中的並行性,並將其拼接為合適的長指令,而G80則只需簡單拆分即可。
另外還需要說明的一點是,R600中每個SP的5個1D ALU並不是全功能的,據相關資料,每組5個ALU中,只有一個能執行函數運算,浮點運算和Multipy運算,但不能進行ADD運算,其餘的4各職能執行MADD運算。而G80的每個1D ALU是全功能的,這一點也在一定程度上影響了R600的效能。
總結:雖然R600的ALU規模遠大於G80,但G80的SP運行頻率幾乎是R600的兩倍,而且G80的體系架構採用完全標量化的計算,資源利用率更高,執行效能也更高,因而總體性能不落後於R600。
第八章:尷尬的中端--Geforce8600簡析
在新一代中端顯卡中,最早發布也是最受關注的莫過於nVidia的G84---Geforce8600系列。
但是相比其高高在上的價格,它的性能表現實在不盡如人意,很多測試中均落後於價格低於它的老一代高端顯卡Geforce7900GS。本章將利用前面討論的結論對G84核心的SP處理能力作簡要地分析。
G84是G80核心的高度精簡版本,SP數量從G80的128個銳減為32個,顯存位寬也降為1/3--128bit。
拋開顯存位寬和TMU ROP,我們著重看SP,G84的SP頻率與核心頻率也不相同,例如8600GT,核心頻率只有540MHZ,shader頻率卻高達1242MHZ,即核心頻率的兩倍多,我們粗略按兩倍記,則G84核心相當於核心shader同步的64(個1D標量) SP,而傳統的VS和PS中ALU是4D的,於是可以說G84的計算能力相當於傳統VS和PS總數為64/4=16的顯卡,粗略比較,它與Geforce7600(PS+VS=17)的計算能力相近。但當然,事實這樣比較是有問題的,因為在G7X中,每個PS中有兩個4D ALU,因而7600的運算能力高於傳統PS+VS=17的顯卡。下面的計算就說明了問題:(MADD操作)
對於7600GT ,VS為4D+1D PS為4D+4D 核心頻率560MHZ 理論峰值浮點運算速度:
560MHZ*(12*(4+4)+5*(1+4))*2=135.52GFLOPS
而對於8600GT:1242MHZ*32*1*2=79.4GFLOPS
由此可見,8600GT的峰值運算速度甚至遠低於上代的7600GT,更不用跟7900GS相比了。但是,實際情況下,迫於傳統架構所限,G7X滿載的情況基本不可能出現,G7X的實際運算速率要遠低於理論值,而對於G8X架構,執行效率則高很多,實際運算速率會更加接近理論極限。而且支持SM4.0的G8X寄存器數目也要遠多於G7X,眾多效率優勢,使得Geforce8600GT僅憑借少量的SP就足以擊敗上代中端7600GT。
但是作為DX10顯卡,僅僅擊敗7600GT顯然不是最終目標,僅32SP的它在計算量要求空前之高的DX10游戲中表現極差,根本不能滿足玩家要求。
總結:8600GT性能上取代7600GT的目標憑借著高效的統一渲染架構總算勉強完成,但過少的SP數量使得其顯然難以擊敗上代高端,更不用說流暢運行DX10游戲了,而高高在上的價位更使其處境不利,歸根到底,nVidia對G84 SP數量的吝嗇以及過高的價格定位造就了Geforce8600的尷尬,因此,就目前的情況來看,選用8600系列顯然不如Geforce7900和RadeonX1950GT來的劃算。
㈡ 電腦中GPU是什麼啊
圖形處理器(英語:Graphics Processing Unit,縮寫:GPU),又稱顯示核心、視覺處理器、顯示晶元,是一種專門在個人電腦、工作站、游戲機和一些移動設備(如平板電腦、智能手機等)上圖像運算工作的微處理器。
GPU是顯示卡的「大腦」,它決定了該顯卡的檔次和大部分性能,同時也是2D顯示卡和3D顯示卡的區別依據。2D顯示晶元在處理3D圖像和特效時主要依賴CPU的處理能力,稱為「軟加速」。3D顯示晶元是將三維圖像和特效處理功能集中在顯示晶元內,也即所謂的「硬體加速」功能。顯示晶元通常是顯示卡上最大的晶元(也是引腳最多的)。現在市場上的顯卡大多採用NVIDIA和 AMD-ATI兩家公司的圖形處理晶元。
拓展資料:
GPU主流供應商
intel:intel不但是世界上最大的CPU生產銷售商,也是世界最大的GPU生產銷售商。 intel的GPU在現在完全是集成顯卡,用於intel的主板和intel的筆記本。要是只按發售數量計算,intel隨著他主板發售的集成GPU占據了整個GPU市場的60%以上。
nVidia:現在最大的獨立顯卡生產銷售商,旗下有民用的Geforce系列,還有專業的Quadro系列。其GPU具有cuda通用運算,PureVideo高清視頻技術,PhysX物理加速,Optimus智能顯卡切換等。
AMD(ATI):世界上第二大的獨立顯卡生產銷售商,他的前身就是ATI。旗下有民用的Radeon系列,還有專業的FireGL系列等。就發售量和發售盈利方面,AMD顯卡方面仍然略輸於nv,不過兩者不相伯仲,差距只是幾個百分點。其GPU具有Stream通用運算,ATI Video Converter視頻轉碼,UVD高清視頻技術,Havok、Bullet和Pixelux DMM三種物理引擎等。
㈢ GPU編程常識求助:cg、opencv、opengl、cuda、glsl等
你好,
首先,cg,opengl,glsl都是跟計算機圖形有關的。cg基本是做渲染的,opengl是一個開源圖形庫,和微軟的direct3D是一樣的。glsl是shading language ,專門用來寫shader的,在GPGPU( general purpose GPU)概念出來之前,好多人用glsl來做並行計算。
其次,CUDA和OpenCL是兩個專門做GPU運算的庫。CUDA非常好用,它有自己的NVCC編譯器,和各個系統都兼容很好,但是僅限於用於NVIDIA自己的顯卡。OpenCL雖然任何顯卡都可以使用,但是它的GPU的代碼要放到單獨的一個文本文件中編譯,操作上要比CUDA要復雜。
最後,其實CUDA和OpenCL學那個多一樣,因為並行運算的思想是一樣的。推薦你兩本書:
Programming Massively Parallel Processors 2nd(入門)
CUDA Programming A Developer-'s Guide to Parallel Computing with GPUs (高級一點)
謝謝,望採納
㈣ gpu二緩一致
gpu二緩一致,GPU的LLC是全部SM共享的,memory-side caching, 採用write-back policy,不存在一致性的問題,在異構架構中,我們可以在CPU和加速器之間暴露一個全局的共享內存介面,我們假設CPU、GPU等設備共享相同的物理內存(如手機上的SoC這種情況),如下圖所示。在這種系統中,共享內存會引發一些新的問題,如什麼是內存一致性模型?內存一致性模型如何實現?加速器和處理器的私有緩存如何保持一致?我們接下來首先討論加速器內的內存一致性和緩存一致性,重點是GPU,然後討論跨加速器的內存一致性和緩存一致性。
異構SoC系統模型
GPU的內存一致性和緩存一致性
早期GPU的架構余前與編程模型
早期GPU主要為並行圖形工作負載設計,特點是數據並行度高,但數據共享、同步和通信程度低。
GPU架構
GPU通常有幾十個內核,叫做流式多處理器(Streaming Multiprocessors,SM),每個SM都是高度多線程的,能夠運行上千條線程,映射到SM上的線程共享L1緩存和本地scratchpad內存,所有的SM都共享一個L2緩存。GPU通常將線程分組執行,稱為warps,一個warp中的所有線程共享PC和堆棧,可以使用掩碼來執行獨立的線程,表明哪些線程在執行,哪些線程沒有在執行,這種並行方式就是我們常聽說的SIMT。但是最近,GPU開始允許一個warp中的線程有獨立的PC和堆棧,允許線程獨立調度,我們接下來也假設線程是可以獨立調度的。
由於圖形工作負載並不經常共享數據或進行同步,早期GPU選擇不在L1緩存實現硬體的緩存一致性。
GPU編程模型
和CPU類似,GPU也有一套虛擬仿配ISA,同時也有一套更高級別的語言框架,如CUDA和OpenCL,框架中的高級語言被編譯成虛擬的ISA,並被翻譯為本地的二進制文件。GPU虛擬ISA和高級語言框架通過被稱為作用域(scope)的線程結構,向程序員暴露GPU架構的層次結構。和CPU相比,GPU線程被分組為叫做Cooperative Thread Arrays(CTA)的集群。CTA作用域指來自同一個CTA的線程集合,保證映射到相同的SM,並共享同一個L1huancun。GPU作用域指的是來自同一個GPU的線程集合,可以來自相同或不同的CTA,並共享L2緩存。最後,系統作用域指整個系統所有線程的集合,共享LLC緩存或統一的共享內存。
這種方式可以在沒有硬體緩存一致性的情況下,用軟體的方式實現數據同步和通信。
GPU內存一致性
GPU支持寬松一致性模型,通過FENCE指令進行同步,但是由於沒有硬體緩存一致性,GPU的FENCE只針對屬於同一CTA的其他線程。GPU的store指令也不保證原子性。
因此,早期GPU明確禁止在CTA組之間進行數據同步,但實踐中可以通過繞過L1,在L2上進行同步。這種方案也有一些問題,繞過L1會導致性能下降,且程序員需要仔細地編寫程序。
測驗問題8:GPU不支持硬體緩存一致性,因此無法實現內存一致性模型。
答:錯誤。早期的GPU不支持硬體緩存一致性,但是支持作用域內的寬松內存一致性模型。
GPGPU的內存一致性和緩存一致性
GPGPU最好滿足以下特點:
嚴格而直觀的內存一致性模型,允許在所有線程之間進行同步
一個能夠實現內存一致性模型的緩存一致性協議,允許高效的數據共享和同步,且保持常規GPU架構的簡單性,因為GPU的主要任務仍然是圖形工作負載
我們可以使用類似多核CPU的方法來實現緩存一致性,使用一種與內存模型無關的協議。然而這種方法並不適用於GPU,主要有兩個原因。首先,類似於CPU的緩存一致性協議在GPU環境下會產生很高的通信開銷,因為L1緩存的總容量通常與L2相當,甚至更大,會產生很大的面積開銷,設計也非常復雜;其次,由於GPU保持著數千個活躍的硬體線程,因此需要跟蹤相應數量的一致性事務,需要大量的硬體開銷。
具體的技術細節可以參考原書(埋坑,GPU的部分確實現在看來有些難理解,等之後學習了GPU的架構之後再回來填坑)。
其他異構系統
我們開始進一步討論如何在多個設備的系統中暴露一個全局的共享內存介面,難點在於每個設備都可能通過不同的一致性協議豎大清來實現不同的內存模型,當多個內存模型不同的設備被集成在一起時,異構系統的內存模型是什麼樣的?如何對這種系統進行編程?如何整合多個設備的緩存一致性協議?我們接下來簡單討論這些問題,並概述設計空間。
異構系統的內存模型
如果兩個設備A和B連接在一起並共享內存,這種情況下的內存模型是什麼樣的?一個符合直覺的答案是選擇其中較弱的一個作為整體的內存模型,但如果兩個內存模型無法比較,這種答案就不可行了。即使兩者可以比較,可能也會有更好的答案。
四個設備組成的異構系統
在如上所示的異構系統中,C1和C2內存模型為SC,C3和C4內存模型為TSO。考慮下面的例子,在第一個例子中,有可能r1和r2同時讀到0,但在第二個例子中插入了FENCE後,r1和r2就不能同時讀到0了,但需要注意的是在SC的線程上仍然不需要插入FENCE,這種系統實際上產生了一個不同於SC和TSO的復合內存模型。
Dekker演算法的例子
在這種系統中變成也是比較困難的,很難直接精確定義復合內存模型,更好的辦法可能是使用HSA或OpenCL等進行編程。
異構系統的緩存一致性協議
通過分層緩存一致性來集成多個設備
考慮兩個多核設備A和B,每個設備都有自己的內存模型,並通過不同的緩存一致性協議來實現內存模型,如上圖所示。我們應該如何將兩個設備集成到一個共享內存異構系統中,並將兩個緩存一致性協議正確連接在一起?答案取決於每個設備的內存操作是否滿足自己的內存排序規則。
分層緩存一致性
在分層緩存一致性系統中,本地緩存一致性控制器收到請求後,首先試圖在本地滿足該請求,如果無法滿足就轉發到全局一致性控制器,再轉發到另一個設備的本地緩存一致性控制器。在這種設計中,全局控制器必須有足夠豐富的介面來滿足各個設備本地控制器發起的請求,且每個本地控制器必須用shim來擴展,作為兩個控制器之間的介面轉換。相關的一些例子可以參考原文。
減少異構系統緩存一致性的帶寬需求
在異構系統中,內核之間的緩存一致性通信帶寬可能成為性能瓶頸。一種解決思路是採用粗粒度的緩存一致性,比如在GPU本地以page大小的粒度進行跟蹤,如果緩存未命中且已知該位置對應的page對GPU來說是私有的或只讀的,就不需要訪問全局的目錄,而是可以從高帶寬的匯流排從內存直接訪問。
CPU-GPU系統中緩存一致性的一個低復雜度解決方案
我們可以採用選擇性的GPU緩存,任何被映射到CPU內存的數據都不會緩存在GPU中,任何來自GPU內存的數據,如果目前被緩存在CPU中,也不會被緩存在GPU中。這個簡單的策略可以很好地實現緩存一致性。為了實現這種方法,GPU維護一個粗粒度的目錄,維護當前由CPU緩存的數據,當CPU訪問GPU內存中的一個緩存塊時,這個緩存塊所在的區域就被插入到目錄中,目錄中所有的位置都不會被緩存到GPU中。不過這種方法也有壞處,即任何被CPU緩存的數據都必須從CPU中取回,為了解決這個問題需要進行進一步的優化,如GPU對CPU的請求進行合並、在GPU上加入一個特殊的CPU側的緩存等。