1. 程式人生 > >CPU預取與效能簡介

CPU預取與效能簡介

隨著計算機硬體的發展,CPU主頻已由過去 MHz 發展到了現在的 GHz,而常用硬碟的存取速率還是幾百MB每秒,雖然現在SSD卡也可以達到幾個GB,但是還是太慢了。
處理器的速度的不停發展,導致磁碟 I/O是整個效能的瓶頸,而且磁碟的訪問速率與 CPU 的速度差距還在持續擴大。 

而儲存介質從光碟、磁碟、記憶體到快取記憶體,速度越來越快,但是成本也越來越高。為了在成本和效能之間進行平衡,現代計算機體系架構往往選擇使用少量效能高但成本也高的儲存器作為速度慢而成本也低的儲存器的快取。 就出現了儲存層次。
1.png
但是即便如此,CPU的一次訪存失敗也會帶來巨大的時鐘週期開銷,如何減少訪存失敗就成了一個關鍵的問題。而預取就是為此而出現。

  1. 預取

    快取技術利用區域性性原理,使速度更快的上層儲存器成為下層儲存器的緩衝。基於技術的限制及成本的考慮,上層儲存器的容量要比下層儲存器小得多。資料如果存在於上層儲存器中,就可以直接對其進行讀寫, 這種情形叫做命中,命中的統計概率叫做命中率;如果未命中就必須涉及到訪問下層儲存器,這種情形也叫失效。
    但是隨著應用規模的不斷擴大快取失效所佔的比例越來越大,成為影響快取效能的主要因素。為了提高快取的命中率,
    預取技術通過計算和訪存的重疊,在Cache可能會發生失效之前發出預取請求以便在該資料真正被使用到時己提前將資料塊取入Cache,從而避免Cache失效造成的處理器停頓。

  2. 關於cache預取

    cache預取是將記憶體中的指令和資料提前存放到本地記憶體(cache memory),從而加快處理器執行速度。這裡分為指令預取和資料預取,資料預取相比指令語句更具有挑戰性,因為資料預取規律更少一點。
    指令預取在INTEL 8086和Motorla 68000就開始了。

  3. Cache預取分類

    Cache預取可以通過硬體或者軟體實現,也就是分為硬體預取和軟體預取兩類。
    硬體預取,是通過處理器中專門的硬體來實現的,該硬體監控正在執行程式中請求的指令或資料,識別下一個程式需要的流然後預取到處理器中。
    軟體預取,是通過編譯器分析程式碼然後在程式編譯的過程中插入prefetech。這樣在執行過程中在指定位置就會進行預取的動作。

  4. 硬體預取

    硬體預取中有Stream buffers方法,由Alan Jay Smith建議,基於"one block lookahead (OBL) scheme"。
    Stream buffers是硬體預取中最常用的方法。最早在1990年由Norman jouppi提出。
    Stream buffers是獨立於cache的buffer。
    CPU發生Cache miss後,如果在stream buffer中查到了相應的資料,則處理器把這個cache block取到cache中。
    與二級cache對比,streambuffer的硬體邏輯很少,訪問stream buffer比訪問二級cache快。如果不快那還不如直接訪問二級cache。
    當在預取機制在記憶體中找到了塊A,那麼會預取連續的A+1,A+2,A+3,A+4。因為處理器消耗完A+1後會接著消耗A+2的,預取連續的塊也叫做順序預取。這個順序預取在預取指令集的時候非常有有用,如下圖。
    2.png


    這個方法可以通過增加stream buffer來放大,對於每個訪問失敗,都會分配一個新的stream buffer。
    而stream buffer的深度則取決於壓測模型和微架構。
    指令的另一個預取方式是提前S個地址進行預取,叫做步幅預取。

  5. 軟體預取

    編譯器指定預取,在大量迭代中非常常用。編譯器預測未來cache miss然後插入預取指令。
    這種預取不會阻塞記憶體操作,不會改變處理器狀態或導致頁錯誤。軟體預取減少了強制的cache miss。
    例如有迴圈如下:
    for (int i=0; i<1024; i++) { array1[i] = 2 * array1[i]; }
    每次迭代,i變數會增加,這樣可以提前讓i進行增加,通過編譯器加入prefetch程式碼如下:
    for (int i=0; i<1024; i++) { prefetch (array1 [i + k]); array1[i] = 2 * array1[i]; }
    這的預取步幅k,取決於兩個因素,1個迭代的時間(假設為7個時鐘週期)和cache miss迭代的時間(假設為49個時鐘週期),那麼k=49/7=7。表示預取7個元素。

  6. 軟硬體預取對比

    軟體預取需要程式設計師或編譯器,硬體預取需要硬體機構。
    軟體預取在有規律的迴圈中實現預取指令,硬體預取可以基於程式的動態執行來工作。
    硬體預取相比軟體預取消耗更少的CPU。
    預取的覆蓋率計算:由於預取消除的cache miss除以總的cache miss就是預取的覆蓋率。如下圖:
    3.png
    預取的精確性,計算方法為預取消除的cache miss除以(無效的預取加上預取消除的cache miss),公式如下圖:
    4.png

  7. 預取對應用影響

    通過以上分析介紹,我們知道預取對程式肯定是會有影響的。但並非所有業務在開啟預取條件都是效能增益的,預取對那些有規律的資料採集和指令執行過程中才會發揮最大功效,而在隨機業務紅預取反而是有害的,因為隨機事務業務中的資料都是隨機的,預取進來的資料在接下去的業務中並不能有效利用只是白白浪費了CACHE空間和資源。
    以JVM效能測試為例子,使用SPECJbb 2005 測試套件。在同一臺SKL機器上進行壓測,我們發現,當ENABLE Prefetch選項後效能是比Disable要低的。

  8. 參考

Intel 平臺程式設計總結----快取優化之資料預取:
http://blog.chinaunix.net/uid-20385936-id-3902562.html
Cache_prefetching
https://en.wikipedia.org/wiki/Cache_prefetching
stream buffer
http://blog.csdn.net/qianlong4526888/article/details/41517303
Optimizing Application Performance on Intel® Core™ Microarchitecture Using Hardware-Implemented Prefetchers
https://software.intel.com/en-us/articles/optimizing-application-performance-on-intel-coret-microarchitecture-using-hardware-implemented-prefetchers