不管是cpu還是gpu都是很高速的裝置,然而從主存中取資料會很慢很慢,為了充分利用高速裝置,二者都使用了快取,程式設計一定要考慮的是電腦程式的區域性性(locality)的基本屬性—–時間區域性性與空間區域性性。多核時代和gpu並行運算時代來臨,另外乙個影響程式執行的速度的關鍵因素—–快取一致性(cache coherency)。這些cpu和gpu都有一些區別,深入底層才能寫出更高效的**!
我覺得在2023年仍然有必要學習cuda。雖然各路大腿子都用自家編的或者優化的編譯器,很多還都是不開源的,但是對我來說使用cuda仍然是最簡單的方式去提公升程式效能。**編的好的話至少比cpu快吧,而且cpu**想寫好了必須彙編優化,這個事幹起來比較蛋疼。
區域性性
時間區域性性:
由於時間區域性性,同一資料物件可能會被多次使用,一旦乙個資料物件在第一次不命中時被拷貝到快取中,我們就會期望後面對該目標有一系列的訪問命中。因為快取比低一層的儲存裝置更快,對後面的命中服務會比最開始的不命中快很多。
空間區域性性
塊通常包含多個資料物件。由於空間區域性性,我們會期望後面對該塊中的其他物件的訪問能夠補償不命中後拷貝該塊的花費。
儲存器層次結構
為了讓cpu不把時間都耗在讀主存上,現代計算機搞了乙個**快取,l1,l2挨著cpu,l3挨著記憶體,這仨都是sram,所以又小又快又貴。他們全部由硬體管理,所以相對不是很靈活。
l1快取記憶體的速度幾乎和暫存器一樣快,典型的是2~4個時鐘週期。
l2大約10個時鐘週期能訪問到
l3需要30~40個時鐘週期
cache對使用者是透明的,很多時候只能猜。c語言中有乙個register修飾符,但是也僅僅是對編譯器的建議,編譯器不一定採用。組成原理會講直接對映,組相聯,全相聯啊之類的東西。這個東西比較迷,我並不知道我以後的電腦用的哪種方式。但是會影響程式效能的就是快取不命中,如果能像做題一樣算出來一段程式的快取命中率就好了。但是不好。那就猜一下。一般來說intel core i7 用的是組相連,而且l1和l2是8路組相連,l3是16路組相連。
很致命的應該是抖動(thrash)。也就是cache反覆的載入和驅逐相同的快取記憶體組.
其他的大致來說有三點
1.cache大小&塊大小:大的能提高空間區域性性的利用,提高命中率卻增加命中時間,損害了時間區域性性。
2.相聯度:高相聯度會降低抖動的可能性,但是增加命中時間,不命中處罰,而且貴。
3.寫策略。
讀比較簡單,命中就返回cpu,不命中就講塊讀到cache裡然後返回給cpu。寫的話要一層一層地來,寫了資料就會髒掉,髒了就會很麻煩。
寫策略比較複雜,cpu和gpu有區別,單核cpu和多核cpu也有區別,這裡先說最簡單的單核cpu。
現在來講簡化的模型是寫回和寫分配(write-back and write-allocate), 比較適合現在的高速cpu。
寫回:
盡可能推遲儲存器更新,只有當替換演算法要驅逐更新過的塊時,才把他寫到緊接著的低一層。由於區域性性,寫會能顯著減少匯流排流量。
寫分配:
當寫不命中的時候,載入相應的低一層塊到cache中,然後更新這個cache塊。寫分配試圖利用寫的空間區域性性,但是缺點是每次不命中都會導致乙個塊從低一層傳送到快取記憶體。
寫回寫分配和讀是對稱的,而且實際上用的比較多
因為快取和快取替換機制都是基於區域性性設計的,所以如果能盡量運用區域性性就可以一定程度上提公升程式效能。
以上都是從理論上來說的。
從實踐來講,主要考察迴圈的使用,特別是迴圈訪問多維陣列的時候。
1.對區域性變數的反覆引用是好的
2.步長為1的引用模式是好的
3.迴圈的排列很重要!
1和2也就是時間區域性性和空間區域性性。第三點更細
比如說乙個三重迴圈,有
ijk,jik,jki,kji,kij,ikj六種排列方式,他們每乙個的效率都是不一樣的。
具體怎麼樣要具體分析。但是在c語言中,陣列是按行順序儲存的,所以訪問應該盡量按行訪問。也就是行》列
比較炫酷的是直接在程式裡把資料分塊,差不多每次都只對整體的一小塊在cache上操作,但是這樣**會很難讀。
還是寫問題。多核cpu的寫問題就比較迷了。
現在我們有多個核,每個核又都有自己的cache和公有的cache。
依然拿intel core i7舉例:
主存:共享
l3:共享
l2:一人一塊
l1:一人兩塊(放資料的和放指令的)
於是問題來了:如果某個cpu快取段中對應的記憶體內容被另外乙個cpu偷偷改了,那就很尷尬了,特別是使用上文提到的寫回模式。
為了解決這個問題,就有了快取一致性協議,以保持快取的完全一致,但這種協議都是有代價的,都是各種限制回寫的規則,使得多核cpu不能發揮1+1=2的效能。代表性的例子是mesi協議,戳這裡詳細了解
快取一致性(cache coherency)入門
乙個記憶體的寫需要通知所有核的各個級別的快取,無論何時,所有處理器的核看到的記憶體檢視都完全一樣。隨著處理器核的數量增多,通知的開銷迅速增加,核心的數量被快取一致性制約了。
手頭的教材是2023年的。gpu發展太快了,所以我並不是很清楚現在的是什麼樣子的。
但還是先說一下現在的吧。深度學習太吃gpu了,學校用的是titan x,電晶體數目高達12,000,000,000,擁有3584個cuda單元。畢竟核彈廠。。
好了不扯其他的回來說組成
區域性性
gpu與cpu乙個很重要的區別就是他的區域性性。
cpu的區域性性是由硬體管理的,程式設計師只能盡量寫出快取友好的**。
而gpu中的區域性性是由程式設計師負責的,程式設計師在需要資料前就把他們裝入cache。cache中最麻煩的還是那些被寫過的髒資料。由程式設計師控制的cache寫,我們就可以把一直在進行的區域性變換變數們放在cache裡並且只在最後寫回全域性記憶體。這就靈活很多啦。但是程式其實很多不是很好並行的,也不是每個程式都有很好的區域性性,這些就自己權衡啦。
組成
匯流排
nvlink則提供了乙個高效率而又高頻寬的鏈結路徑,可以使gpu與cpu的儲存系統之間有5~12倍於pci-e 3.0的頻寬,也就是說頻寬能夠達到80gb/s~近200gb/s。如果您的cpu不支援nvlink,這個匯流排仍然可以互連gpu與gpu。nvlink的能效可以達到pci-e 3.0的兩倍以上。
但是根據我的理解和實踐經驗,這件事並沒有這麼簡單。首先是學校的機子。
tensorflow跑cifar10的時候用了四張卡。但是開頭會有報告gpu的使用情況。
學校的gpu是0和1互聯,2和3互聯。感覺上互聯應該就是nvlink,不互聯就是pci-e。所以我之前的玩具**使用率才20–40%應該是資料走pci-e太多了,並且經常往返於cpu和gpu。最後計時我的筆記本和4titan一樣了
群裡的大神說:一定要避免乙個流程反覆進入gpu,就是避免在每個step迴圈內部多次sess.run的情況(tensorflow)
另外聽說天價微型超算dgx-1也是只能三卡互聯,想要八卡並行的話比較好的解決方案是通過一張gpu中轉,而不是走cpu。不過這個跟我沒什麼關係,就瞎說。
gpu硬體結構
sp: 最基本的處理單元,streaming processor 最後具體的指令和任務都是在sp上處理的。gpu進行平行計算,也就是很多個sp同時做處理
sm:多個sp加上其他的一些資源組成乙個sm, streaming multiprocessor. 其他資源也就是儲存資源,共享記憶體,寄儲器等。
warp:gpu執行程式時的排程單位,目前cuda的warp的大小為32,同在乙個warp的執行緒,以不同資料資源執行相同的指令。
grid、block、thread:在利用cuda進行程式設計時,乙個grid分為多個block,而乙個block分為多個thread.其中任務劃分到是否影響最後的執行效果。劃分的依據是任務特性和gpu本身的硬體特性。
快取
gpu是非快取一致系統的,他不會自動更新其他核的快取,需要由程式設計師寫清楚每個處理器的目標區域
一般兩級快取。
sm下方的是l1 cache
texture memory:針對global memory的乙個特殊檢視,用來儲存差值計算所需的資料,擁有基於硬體進行插值的特性。
constant memory:儲存唯讀資料,所有gpu卡均對其快取,也是global memory的乙個檢視
l1下方就是l2 cache
shared memory:這個是程式設計師可控的cache,與cpu不同,他沒有自動完成資料替換的硬體邏輯,而是完全由程式設計師控制。
CPU與GPU效能的比較報告
在一塊p100gpu 視訊記憶體16276mib 效能如下 由上圖可見,隨著程序數目的增大耗時會線性增加。當然,如果rt滿足要求,卡上可以同時部署其他任務。intel r xeon r cpu e5 2620 v3 2.40ghz 24核伺服器下。tf預設為盡可能的占用所有的核,真正的neuron服...
Pytorch 比較CPU和GPU的運算速度
在跑神經網路的時候,gpu的作用是很明顯的。下面比較一下cpu跑和gpu跑的區別 先用cpu跑 import torch import time for i in range 1 10 start time time.time 返回當前語句執行時的時間點 單位秒 a torch.rand i 100...
CPU的結構與組成
cpu主要包括控制器 運算器 暫存器組和內部匯流排構成。暫存器 可用來暫存指令 資料等處理物件,可以將其看做是記憶體的一種。根據種類的不同,乙個cpu內部會有20 100個暫存器。下圖的中斷系統可以包含在cu內。匯流排是一組可為多個功能部件共享的公共資訊傳送線路。為保證匯流排上資訊不至於衝突,共享匯...