2009-11-16 20 views
9

मैंने हाल ही में अपने आवेदन में झूठी साझा करने वाली समस्या का सामना किया है, और मैंने Sutter's article को कैश लाइनों पर अपने डेटा को संरेखित करने के तरीके पर देखा है। वह निम्नलिखित सी ++ कोड पता चलता है:कैश लाइन संरेखण (आलेख पर स्पष्टीकरण की आवश्यकता है)

// C++ (using C++0x alignment syntax) 
template<typename T> 
struct cache_line_storage { 
    [[ align(CACHE_LINE_SIZE) ]] T data; 
    char pad[ CACHE_LINE_SIZE > sizeof(T) 
     ? CACHE_LINE_SIZE - sizeof(T) 
     : 1 ]; 
}; 

मैं यह कैसे काम करेगा जब CACHE_LINE_SIZE > sizeof(T) सच है देख सकते हैं - struct cache_line_storage सिर्फ स्मृति में से एक पूर्ण कैश लाइन को ले जा रही समाप्त होता है। हालांकि, जब sizeof(T) एक कैश लाइन से बड़ा होता है, तो मुझे लगता है कि हमें CACHE_LINE_SIZE - T % CACHE_LINE_SIZE बाइट्स द्वारा डेटा पैड करना चाहिए, ताकि परिणामस्वरूप संरचना का आकार हो जो कैश लाइन आकार का एक अभिन्न अंग है। मेरी समझ में क्या गलत है? 1 बाइट के साथ पैडिंग पर्याप्त क्यों है?

उत्तर

7

आपके पास आकार 0 के सरणी नहीं हो सकते हैं, इसलिए इसे संकलित करने के लिए 1 आवश्यक है। हालांकि, spec का वर्तमान मसौदा संस्करण कहता है कि इस तरह की पैडिंग अनावश्यक है; कंपाइलर को संरचना के संरेखण तक पैड करना होगा।

ध्यान दें कि CACHE_LINE_SIZEalignof(T) से छोटा है तो यह कोड खराब हो गया है। इसे ठीक करने के लिए, आपको शायद [[align(CACHE_LINE_SIZE), align(T)]] का उपयोग करना चाहिए, जो यह सुनिश्चित करेगा कि एक छोटा संरेखण कभी नहीं उठाया जाता है।

+0

+1, हालांकि व्यवहार में, मुझे किसी भी मामले से अवगत नहीं है जहां संरचना संरेखण कैशलाइन आकार से अधिक हो सकता है। सभी प्रकार के संरेखण बाधाओं के बाद आम तौर पर कैशलाइन बाधाओं से आते हैं। – Bahbar

+1

क्या आपके सुझाव में संरचना या संरचना के पहले तत्व पर लागू संरेखण है? –

+1

लेकिन झूठी-साझाकरण के मैकेनिक्स के लिए .. इसे रोकने के लिए, 't' को कैश लाइन आकार के अभिन्न एकाधिक से गठबंधन नहीं किया जाना चाहिए, भले ही' sizeof (T)> CACHE_LINE_SIZE'? या यह आवश्यक नहीं है? – int3

3

#define CACHE_LINE_SIZE 32 
sizeof(T) == 48 

कल्पना अब, पर विचार कैसे [[ align(CACHE_LINE_SIZE) ]], काम करता है। उदाहरण के लिए:

[[ align(32) ]] Foo foo; 

यह कुछ n के लिए sizeof(Foo) == 32n बाध्य करेगा। यानी Foo foo[10]; जैसी चीजों के लिए, प्रत्येक foo[i] अनुरोध के रूप में गठबंधन करने के लिए, यदि आवश्यक हो, तो आपके लिए संरेखित होगा)।

तो, हमारे मामले में, sizeof(T) == 48 के साथ, इसका मतलब sizeof(cache_line_storage<T>) == 64 है।

तो संरेखण आपको वह पैडिंग देता है जिसकी आप उम्मीद कर रहे थे।

हालांकि, यह टेम्पलेट में एक 'त्रुटि' है। इस मामले पर विचार करें:

#define CACHE_LINE_SIZE 32 
sizeof(T) == 32 

यहाँ हम char pad[1]; साथ खत्म। जिसका अर्थ है sizeof(cache_line_storage<T>) == 64। शायद आप जो चाहते हैं नहीं!

मुझे लगता है कि कुछ हद तक टेम्पलेट संशोधित करने की आवश्यकता होगी:

template <typename T, int padding> 
struct pad_or_not 
{ 
    T data; 
    char pad[padding]; 
}; 

// specialize the 0 case 
// As it is late, I am SURE I've got the specialization syntax wrong... 
template <typename T, int> 
struct pad_or_not<0> 
{ 
    T data; 
}; 

template<typename T> 
struct cache_line_storage { 
    [[ align(CACHE_LINE_SIZE) ]] pad_or_not<T, (sizeof(T) > CACHE_LINE_SIZE ? 0 : CACHE_LINE_SIZE - sizeof(T)) > data; 
}; 

या कुछ इस तरह।

0

"आपके पास आकार 0 के सरणी नहीं हो सकते हैं, इसलिए इसे संकलित करने के लिए 1 आवश्यक है" - जीएनयू सी सरणी को शून्य के रूप में आयाम की अनुमति देता है। http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html

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