2011-12-12 3 views
50

दिमित्री Vyukov उत्तम घिरा mpmc कतार C++ देखें लिखित में: http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queueलाइन आकार कैश करने के लिए कैसे और कब संरेखित करें?

वह कुछ गद्दी चर कहते हैं। मुझे लगता है कि इसे प्रदर्शन के लिए कैश लाइन में संरेखित करना है।

मेरे कुछ प्रश्न हैं।

  1. ऐसा क्यों किया जाता है?
  2. क्या यह एक पोर्टेबल विधि है जो हमेशा
  3. __attribute__ ((aligned (64))) का उपयोग करने के लिए सबसे अच्छा होगा।
  4. बफर पॉइंटर प्रदर्शन से पहले पैडिंग क्यों करेगा? कैश में लोड सूचक नहीं है, तो यह वास्तव में केवल एक सूचक का आकार है?

    static size_t const  cacheline_size = 64; 
    typedef char   cacheline_pad_t [cacheline_size]; 
    
    cacheline_pad_t   pad0_; 
    cell_t* const   buffer_; 
    size_t const   buffer_mask_; 
    cacheline_pad_t   pad1_; 
    std::atomic<size_t>  enqueue_pos_; 
    cacheline_pad_t   pad2_; 
    std::atomic<size_t>  dequeue_pos_; 
    cacheline_pad_t   pad3_; 
    

चाहेंगे ग कोड के लिए जीसीसी के तहत इस अवधारणा काम करता है?

उत्तर

34

यह इस तरह से किया जाता है ताकि अलग-अलग क्षेत्रों को संशोधित करने वाले विभिन्न कोरों को कैश लाइन को उछालने की आवश्यकता न हो, जिनमें से दोनों अपने कैश के बीच हों। आम तौर पर, प्रोसेसर के लिए स्मृति में कुछ डेटा तक पहुंचने के लिए, इसमें मौजूद संपूर्ण कैश लाइन उस प्रोसेसर के स्थानीय कैश में होनी चाहिए। यदि यह डेटा संशोधित कर रहा है, तो कैश प्रविष्टि आमतौर पर सिस्टम में किसी भी कैश में एकमात्र प्रतिलिपि होनी चाहिए (एमईएसआई/MOESI- शैली कैश समेकन प्रोटोकॉल में विशिष्ट मोड)। जब अलग-अलग कोर एक ही कैश लाइन पर रहने के लिए होने वाले विभिन्न डेटा को संशोधित करने का प्रयास करते हैं, और इस प्रकार पूरे लाइन को आगे और पीछे ले जाने में समय बर्बाद कर देते हैं, जिसे झूठी साझाकरण के रूप में जाना जाता है।

विशिष्ट उदाहरण आप देते हैं, एक कोर एक प्रवेश enqueueing किया जा सकता है (पढ़ने (साझा) buffer_ और लेखन (अनन्य) केवल enqueue_pos_), जबकि एक अन्य dequeues (साझा buffer_ और अनन्य dequeue_pos_) या तो केंद्र के बिना, एक कैश लाइन पर रोकने दूसरे के स्वामित्व में।

शुरुआत में पैडिंग का अर्थ है कि buffer_ और buffer_mask_ दो पंक्तियों में विभाजित होने के बजाय, उसी कैश लाइन पर समाप्त होता है और इस प्रकार स्मृति मेमोरी को एक्सेस करने की आवश्यकता होती है।

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

attribute दृष्टिकोण अधिक संकलक विशिष्ट होगा, लेकिन, छमाही में इस संरचना के आकार में कटौती हो सकती है के बाद से गद्दी एक पूर्ण कैश लाइन के लिए प्रत्येक तत्व आगे निकलने के लिए सीमित होगी। अगर उनमें से बहुत कुछ था तो यह काफी फायदेमंद हो सकता है।

वही अवधारणा सी और साथ ही सी ++ में भी लागू होती है।

+0

@ नोवेलक्रेट - ठीक है जो बहुत समझ में आता है। तो प्रश्न 2 और 3 के बारे में क्या? – Matt

+9

@MattH: पोर्टेबिलिटी के लिए सी ++ 11 'std :: aligned_storage' प्रस्तुत करता है जो आपको परिभाषित आकार और संरेखण के संग्रहण की आवश्यकता होती है।'Char [N]' के लिए डिफ़ॉल्ट संरेखण अन्यथा '1' है। –

+1

लिंकर पैडिंग चर को ऑप्टिमाइज़ क्यों नहीं करेगा अगर उनका उपयोग नहीं किया जाता है? – RishiD

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