2012-09-25 12 views
10

का उपयोग कर सी में वैश्विक साझा स्थिति के संशोधन के लिए लॉक-फ्री चेक संपादित करें: एसटी नए लोगों के लिए दो से अधिक लिंक पोस्ट करने की अनुमति नहीं देता है। गायब संदर्भों के लिए खेद है।कैश-लाइन संरेखण

मैं एक सी अनुप्रयोग में लॉकिंग ओवरहेड को कम करने की कोशिश कर रहा हूं जहां वैश्विक स्थिति में परिवर्तन का पता लगाना प्रासंगिक है। भले ही मैं हाल ही में इस विषय पर बहुत कुछ पढ़ रहा हूं (उदाहरण के लिए एच। सटर से बहुत कुछ, और बहुत कुछ) मैं अपने कार्यान्वयन के बारे में आश्वस्त होने में विफल रहता हूं। मैं डेटा से अधिक थ्रेड के बीच साझा से धागा स्थानीय डेटा अद्यतन करने के लिए एक कैश लाइन निरपेक्ष वैश्विक चर पर एक जाँच के लिए एक कैस संचालन और DCL तरह के संयोजन का उपयोग करने के लिए, इस प्रकार झूठे के बंटवारे से परहेज, चाहते हैं। विश्वास की मेरी कमी है मुख्य रूप से

  1. करने के लिए मुझे Type-Attributes
  2. मैं ऐसे aligning- रूप में किसी भी साहित्य और है कि मैं आसानी से सेल्सियस के लिए उसका अनुवाद कर सकें उदाहरण खोजने के लिए, सक्षम नहीं होने लगते पर जीएनयू प्रलेखन की व्याख्या करने में नाकाम रहने के कारण को-संचय-लाइन और जानने--संचय-लाइन आकार अनुसूचित जनजाति या 1 पर
  3. सी के साथ मेरा अनुभव है (हालांकि मेरे सवाल का जवाब करने के लिए कुछ हद तक मैं अपने कार्यान्वयन के साथ आश्वस्त नहीं हूँ लगता है) सीमित

मेरे सवालों का:

  1. टाइप गुण प्रलेखन राज्यों:

    यह विशेषता एक न्यूनतम संरेखण (बाइट्स में) निर्दिष्ट निर्दिष्ट प्रकार के चर के लिए। उदाहरण के लिए, घोषणाओं:

    (कृपया घोषणा के लिए टाइप-गुण दस्तावेज़ देखें)

    बल संकलक बीमा करने के लिए (जहाँ तक यह कर सकते हैं) है कि प्रत्येक चर जिसका प्रकार struct S या more_aligned_int आवंटित किया जाएगा और है कम से कम 8-byte सीमा पर गठबंधन किया गया। एक स्पार्क पर, प्रकार struct S8-byte सीमाओं के अनुरूप की सभी चर होने जब दूसरे के लिए के प्रकार struct एस एक चर को कॉपी, इस प्रकार रन-टाइम दक्षता में सुधार लाने संकलक ldd और एसटीडी (doubleword लोड और दुकान) निर्देशों का उपयोग करने की अनुमति देता ।

    मतलब यह है कि कि struct S या more_aligned_int की शुरुआत हमेशा 8-byte सीमा के अनुरूप किया जाएगा? इसका मतलब यह नहीं है कि डेटा को 64 बाइट्स का उपयोग करने के लिए पैड किया जाएगा, है ना?

  2. मान लीजिए 1।सच है कि struct cache_line_aligned के प्रत्येक उदाहरण (देखें कोड नीचे उदाहरण 1) 64-byte सीमाओं पर संरेखित करता है और वास्तव में एक कैश लाइन का उपयोग

  3. typedef का उपयोग प्रकार घोषणा के लिए नहीं है (यह मानते हुए कैश लाइनों लंबाई में 64 bytes कर रहे हैं) __attribute__ ((aligned (64))) के शब्दों को बदल (देखें कोड उदाहरण 2 नीचे)

  4. मैं जब struct instantiating यदि struct __attribute__ ...

  5. साथ घोषित किया जाता है aligned_malloc उपयोग करने के लिए की जरूरत नहीं है
// 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 

आप struct cache_line_aligned गैर गतिशील का एक उदाहरण (IOW, malloc() और इस तरह के माध्यम से नहीं) बनाते हैं, तो जैसे

यह एक छोटा सा प्रदर्शन है उपरोक्त कोड में, यह गठबंधन किया जाएगा।

सी मानक (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 ऊपर struct की तरह कृत्रिम रूप से गठबंधन/गद्देदार प्रकार में शामिल नहीं है, क्योंकि में __attribute__ ((aligned (64))) ऐसा कुछ नहीं है वहाँ सी मानक। यह यहां एक जीएनयू एक्सटेंशन है। मनमानी संरेखण वाले गतिशील रूप से आवंटित वस्तुओं के लिए आपको उचित मेमोरी आवंटन फ़ंक्शन का उपयोग करना होगा या संरेखण मैन्युअल रूप से करना होगा (अधिक मेमोरी आवंटित करके और फिर सूचक मूल्य "संरेखित करें)।

+0

चीयर्स! इसने चीजों को बहुत अच्छी तरह से स्पष्ट किया है। मैंने संरेखण की जांच करने के लिए आकार का उपयोग करने का विचार नहीं किया है! मुझे यह याद होगा। गतिशील रूप से आवंटित गठबंधन structs के बारे में क्या? क्या 'aligned_malloc' नौकरी करेगा? – instilled

+0

शायद यह होगा। सुनिश्चित करने के लिए अपने दस्तावेज़ पढ़ें। –

+0

ज़रूर! ऐसा करेंगे। शानदार जवाब के लिए फिर से धन्यवाद। – instilled

संबंधित मुद्दे