多核程式探秘(1) false sharing及使用vtune驗證

來源:互聯網
上載者:User

多核開發中常見的一個問題是false sharing(失效共用),這個問題讓我們用一個全新的角度來看待多核程式的編寫,這個角度就是硬體的角度。

 

Intel Core 2 Duo處理器平台上, L2 cache是由兩個core共用的,而L1 data cache是分開的,由兩個core分別存取。cache line的大小是64 Bytes。當不同的線程同時讀寫不同的,看起來更不相關的2個變數時,由於這2個變數實際儲存在同一條cache line上,從而會暗地裡造成cache line的存取違規而導致潛在的效能損失。例如這段代碼:

unsigned char VectorA[10];
unsigned char VectorB[10];

 

UINT MyThreadProcA( LPVOID pParam )
{
     unsigned long long myCounter = 100000000;
     while(--myCounter)
     {
         for (int i=0; i<10; ++i)
         {
             ++VectorA[i];
         }
     }
    return 0;   // thread completed successfully
}

 

UINT MyThreadProcB( LPVOID pParam )
{
     unsigned long long myCounter = 100000000;
     while(--myCounter)
     {
         for (int i=0; i<10; ++i)
         {
             ++VectorB[i];
         }
     }
    return 0;   // thread completed successfully
}

 

儘管MyThreadProc[A/B] 是兩個不同的線程,訪問的也是兩個不同的變數,但是,false sharing卻真真實實的發生了。當MyThreadProcA更新VectorA[i]的時候,對應的Core A上的cache line同時被更新,變為modified狀態,而這個cache line中又儲存了VectorB[i]的一份copy,因此,另一個Core B中的cacheline就會變為失效狀態(invalid),CPU會不得不通過cache protocol(cache的同步協議)去通知Core B上的cache line同時更新VectorB的資料,這樣,儘管MyThreadProcA沒有修改VectorB,卻會導致MyThreadProcB線程訪問VectorB時cache miss增加!而我們知道,cache的訪問速度是普通記憶體的10倍,cache miss增大自然會造成明顯的效能下降!

 

在Core2平台上,可以使用EXT_SNOOP.ALL_AGENTS.HITM 事件來評測false sharing的影響,它監測的是匯流排(記憶體匯流排)傳輸的情況,如果HITM事件發生,則表明匯流排上響應端的cache正處於修改狀態,這恰恰反映了false sharing問題的根源。

vtune的手冊對於EXT_SNOOP.ALL_AGENTS.HITM 的解釋的:

This event counts the snoop responses to bus transactions. Responses can be counted separately by type and by bus agent. With the 'THIS_AGENT' mask the event counts snoop responses from this processor to bus transactions sent by this processor. With the 'ALL_AGENTS' mask the event counts all snoop responses seen on the bus.

 

先看看看看上面這段代碼的測量結果吧!


 

採用sampling測量,EXT_SNOOP.ALL_AGENTS.HITM 發生次數1175次,CPU_CLK 為6373,INST_RETIRED為3796

 

false sharing的解決也很簡單,只要把共用的資料放到不同的cache line中即可,例如,將代碼改為:

 

unsigned char VectorA[100];
unsigned char VectorB[100];

 

這樣,使用的仍然是VectorA[0~9]和VectorB[0~9],VectorA[10~99]則充當了一個pad預留位置,把同一條cache line(64bytes)佔滿。

 

解決false sharing問題後的測量資料為:

 

 

EXT_SNOOP.ALL_AGENTS.HITM 顯著降到179次,CPU_CLK 降為1847,由於指令個數沒有太大變化,INST_RETIRED為3370。通過程式中內嵌計時函數的方法也能得到接近的結果。

 

總結,解決false sharing問題的方法:

1. 增大數組元素的間隔使得由不同線程存取的元素位於不同的cache line上
2. 在每個線程中建立全域數組各個元素的本地拷貝,然後結束後再寫回全域數組

false sharing是多核程式開發的常見問題,需要引起程式員們的重視。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.