2012-09-25 31 views
10

編輯:ST不允許爲新手發佈兩個以上的鏈接。抱歉缺少參考。使用Cache-Line對齊方式在C中修改全局共享狀態的無鎖檢查

我試圖減少C應用程序檢測全局狀態變化的性能相關的鎖定開銷。儘管最近我在這個主題上閱讀了很多內容(例如H. Sutter等等),但我對自己的實施沒有信心。我想使用CAS類似的操作和DCL的組合來檢查全局變量,從而避免虛假共享,以便從多個線程之間共享的數據更新線程本地數據時檢查全局變量的高速緩存行對齊。我的信心不足的主要原因是

  1. 我無法解釋在Type-Attributes
  2. 我似乎沒有能夠找到任何文學和例子,我可以很容易地轉換爲C,如aligning- GNU的文檔(儘管似乎回答我的問題有點我對我的執行沒有信心)
  3. 我對C的經驗是有限公司

我的問題:

  1. 該類型的屬性文檔狀態:

    該屬性指定一個最小對齊(以字節計)爲指定 類型的變量。例如,聲明:

    (請參見聲明類型的屬性的文檔)

    力編譯器,以確保(只要它可以)中,每個可變其類型是struct Smore_aligned_int將被分配並至少在一個8-byte邊界上對齊。在 SPARC中,將struct S類型的所有變量對齊到8-byte的邊界允許 編譯器在將一個類型爲struct S的變量 複製到另一個時使用ldd和std(雙字加載和存儲)指令,從而提高運行時效率。

    這是否意味着的struct Smore_aligned_int開始將始終對準8-byte邊界?這並不意味着數據將被填充爲恰好使用64個字節,對吧?

  2. 假設1。誠然,struct cache_line_aligned每個實例(見下文代碼實施例1)對準上64-byte邊界和利用正好一個高速緩存行(假定高速緩存行的長度是64 bytes

  3. 使用typedef的類型聲明不改變的__attribute__ ((aligned (64)))語義(見下文代碼實施例2

  4. 實例化結構時,如果結構與__attribute__ ...

  5. 聲明我不需要使用
// Example 1 
struct cache_line_aligned { 
 int version; 
 char padding[60]; 
} __attribute__ ((aligned (64))); 

// Example 2 
typedef struct { 
 int version; 
    // place '__attribute__ ((aligned (64)))' after 'int version' 
    // or at the end of the declaration 
 char padding[60]; 
} cache_line_aligned2 __attribute__ ((aligned (64))); 

最後使用高速緩存行排列的方法來有效地檢查,如果全局狀態已被其他線程修改函數的草圖:

void lazy_update_if_changed(int &t_version, char *t_data) { 
    // Assuming 'g_cache_line_aligned' is an instance of 
    // 'struct cache_line_aligned' or 'struct cache_line_aligned2' 
    // and variables prefixed with 't_' being thread local 
    if(g_cache_line_aligned.version == t_version) { 
    // do nothing and return 
    } else { 
    // enter critical section (acquire lock e.g. with pthread_mutex_lock) 
    t_version = g_cache_line_aligned.version 
    // read other data that requires locking where changes are notified 
    // by modifying 'g_cache_line_aligned.version', e.g. t_data 
    // leave critical section 
    } 
} 

很抱歉的長期職位。

謝謝!

回答

7

當你定義一個對齊的類型,比如說,對齊到8字節的邊界時,編譯器應該通過填充使該類型成爲對齊的倍數(這裏是8個字節的倍數)。

理由很簡單。假設你想定義一個對齊類型的數組。當然,它的每個元素也應該對齊。這就是爲什麼可能會有填充。

這裏有一個小演示:

#include <stdio.h> 

struct cache_line_aligned { 
    int version; 
// char padding[60]; 
} __attribute__ ((aligned (64))); 

int main(void) 
{ 
    struct cache_line_aligned s; 
    struct cache_line_aligned a[2]; 
    printf("sizeof(struct cache_line_aligned) = %d\n", (int)sizeof(struct cache_line_aligned)); 
    printf("sizeof(s) = %d\n", (int)sizeof(s)); 
    printf("sizeof(a[0]) = %d\n", (int)sizeof(a[0])); 
    printf("sizeof(a) = %d\n", (int)sizeof(a)); 
    return 0; 
} 

輸出(ideone):

sizeof(struct cache_line_aligned) = 64 
sizeof(s) = 64 
sizeof(a[0]) = 64 
sizeof(a) = 128 

如果創建(不是通過malloc()和這樣IOW)的struct cache_line_aligned非動態的實例,就像在上面的代碼中,它將被對齊。

C標準(1999年)爲malloc()calloc()realloc()規定:

The pointer returned if the allocation succeeds is suitably aligned so that 
it may be assigned to a pointer to any type of object and then used to 
access such an object or an array of such objects in the space allocated 
(until the space is explicitly deallocated). 

哪裏any type of object不包括人爲地對齊/填充類型,如上面的結構,因爲沒有像__attribute__ ((aligned (64)))什麼C標準。這是一個GNU擴展。對於任意對齊的動態分配對象,您必須使用適當的內存分配函數或手動執行對齊操作(通過分配更多內存然後「對齊」指針值)。

+0

乾杯!這已經很好地闡明瞭一些事情。我沒有想過用sizeof來檢查對齊!我會記住這一個。那麼動態分配的對齊結構呢? 'aligned_malloc'會完成這項工作嗎? – instilled

+0

它可能會。閱讀其文檔以確保。 –

+0

當然!會這樣做。再次感謝您的出色答案。 – instilled