2011-04-06 14 views
6

का समर्थन करते हैं, मेरे पिछले question से एक फॉलोअप के रूप में, atomic<T> कक्षा memory_order पैरामीटर के साथ अधिकांश संचालन निर्दिष्ट करती है। एक बाड़ के विपरीत यह स्मृति आदेश केवल उस परमाणु को प्रभावित करता है जिस पर यह काम करता है। संभावित रूप से ऐसे कई परमाणुओं का उपयोग करके आप एक समवर्ती एल्गोरिदम बना सकते हैं जहां अन्य स्मृति का क्रम महत्वहीन है।सी ++ 0 एक्स मेमोरी_ऑर्डर बिना बाड़, अनुप्रयोग, चिप्स जो

  1. किसी एक एल्गोरिथ्म/स्थिति यह है कि अलग-अलग परमाणु चर का आदेश देने से लाभ होगा और नहीं बाड़ की आवश्यकता का एक उदाहरण के लिए मुझे बात कर सकते हैं:

    तो मैं दो प्रश्न हैं?

  2. कौन सा आधुनिक प्रोसेसर इस प्रकार के व्यवहार का समर्थन करते हैं? यही वह जगह है, जहां संकलक सिर्फ सामान्य बाड़ को सामान्य बाड़ में अनुवाद नहीं करेगा।

उत्तर

4

स्मृति आदेश कार्यों पर std::atomic<T> चर पर पैरामीटर नहीं कि आपरेशन से प्रति के आदेश को प्रभावित करता है, यह आदेश देने के रिश्तों कि आपरेशन अन्य कार्यों के साथ बनाता है प्रभावित करता है।

उदा। a.store(std::memory_order_release) अपने आप ही आप कैसे a पर कार्रवाई कुछ और के संबंध में आदेश दिया, लेकिन एक और धागे से a.load(std::memory_order_acquire) के लिए एक कॉल के साथ जोड़ा जाता है, इस तो अन्य संचालन के आदेश के बारे में कुछ भी नहीं बताता है --- सभी अन्य चर लिखते (सहित गैर-परमाणु वाले) थ्रेड द्वारा किए गए स्टोर को a पर लोड किया गया था, जो भार लोड किया गया था, अगर वह लोड संग्रहीत मूल्य को पढ़ता है।

आधुनिक प्रोसेसर पर, संचालन पर कुछ स्मृति आदेश नो-ऑप्स नहीं हैं। जैसे x86, memory_order_acquire, memory_order_consume और memory_order_release लोड और स्टोर निर्देशों में निहित हैं, और अलग-अलग बाड़ की आवश्यकता नहीं है। इन मामलों में ऑर्डरिंग संकलक को पुन: निर्देशित करने वाले निर्देश को प्रभावित करती है।

स्पष्टीकरण: दिए गए निर्देशों में निहित बाड़ मतलब हो सकता है कि संकलक किसी भी स्पष्ट बाड़ निर्देश जारी करने के लिए करता है, तो सभी स्मृति आदेश की कमी परमाणु चर पर अलग-अलग संचालन से जुड़े होते हैं की जरूरत नहीं है। यदि आप सबकुछ के लिए memory_order_relaxed का उपयोग करते हैं, और स्पष्ट बाड़ जोड़ते हैं तो संकलक को उन बाड़ों को निर्देशों के रूप में स्पष्ट रूप से जारी करना पड़ सकता है।

उदा। x86 पर, XCHG निर्देश इसके साथ एक अंतर्निहित memory_order_seq_cst बाड़ है। वहाँ इस प्रकार 86 पर नीचे दो विनिमय के संचालन के लिए तैयार किए गए कोड के बीच कोई अंतर नहीं है --- वे एक ही XCHG अनुदेश के दोनों नक्शा:

std::atomic<int> ai; 
ai.exchange(3,std::memory_order_relaxed); 
ai.exchange(3,std::memory_order_seq_cst); 

हालांकि, मैं अभी तक किसी भी संकलक कि छुटकारा पाने के बारे में पता नहीं कर रहा हूँ निम्नलिखित कोड में स्पष्ट बाड़ निर्देश की:

std::atomic_thread_fence(std::memory_order_seq_cst); 
ai.exchange(3,std::memory_order_relaxed); 
std::atomic_thread_fence(std::memory_order_seq_cst); 

मैं compilers कि अनुकूलन अंततः संभाल लेंगे उम्मीद है, लेकिन वहाँ अन्य इसी तरह के मामलों में जहां अंतर्निहित बाड़ बेहतर अनुकूलन की अनुमति देगा रहे हैं।

इसके अलावा, std::memory_order_consumeकेवल चर पर प्रत्यक्ष संचालन के लिए लागू किया जा सकता है।

+0

हां, मैं इसे समझता हूं, यही मेरा मतलब है * यह स्मृति आदेश केवल उस परमाणु को प्रभावित करता है जिस पर यह कार्य करता है *। दोनों प्रश्न अभी भी खड़े हैं। –

+0

यदि * * परमाणु 'पर मेमोरी ऑर्डर निर्दिष्ट करके * रिश्ते की सिंक्रनाइज़ेशन की गारंटी दी जाती है, और एक बाड़ केवल 'परमाणु ' ऑपरेशन के साथ काम करने की गारंटी है, तो मानक में बाड़ भी क्यों हैं। बस चर पर स्मृति आदेश का उपयोग किसी भी बाड़ की आवश्यकता को रोक देगा। और चूंकि आपको परमाणु के बिना बाड़ का उपयोग करने की अनुमति नहीं है, इसलिए मुझे ऐसी स्थिति दिखाई नहीं दे रही है जहां आप वास्तव में बाड़ चाहते हैं। –

+1

एक सशर्त बाड़ एक ऐसी स्थिति है जहां आप एक स्पष्ट बाड़ का उपयोग करना चाहते हैं। जैसे 'std :: परमाणु पी; अगर (पी.लोड (std :: memory_order_relaxed)) { std :: thread_fence (std :: memory_order_acquire); do_something_with (* पी); } ' या एक स्पिन प्रतीक्षा पाश के बाद: (! P.load (std :: memory_order_relaxed)) ' जबकि { std :: this_thread :: उपज(); } std :: thread_fence (std :: memory_order_acquire); ' –