std::atomic_uint64_t writing_ {0};
std::atomic_uint64_t reading_ {0};
std::array<type, size> storage_ {};

bool try_enqueue(type t) noexcept
{
    const std::uint64_t writing {
        writing_.load(std::memory_order::memory_order_relaxed)};
    const auto last_read {reading_.load(std::memory_order::memory_order_relaxed)};
    if (writing - last_read < size) {
        storage_.at(writing & (size - 1)) = t;
        writing_.store(writing + 1, std::memory_order::memory_order_release);

        return true;
    }
    else
        return false;
}

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

थोड़ा और विशेष रूप से, क्या प्रोसेसर सट्टा रूप से लिखने को निष्पादित कर सकता है (जब स्थिति अंततः झूठी का मूल्यांकन करेगी), एक और धागा लेखन को होने के रूप में देखता है, और फिर सट्टा लेखन को त्यागने वाला पहला धागा?

(नोट: यह एकल-उत्पादक एकल-उपभोक्ता है)

5
D. Detweiler 14 सितंबर 2019, 19:53

1 उत्तर

सबसे बढ़िया उत्तर

क्या यह सही है कि किसी ऑपरेशन को सशर्त होने से पहले होने के रूप में नहीं माना जा सकता है, इसके बाद इसे अनुक्रमित किया जाता है?

सी ++ कंपाइलर्स को निश्चित रूप से atomic (या volatile) ऑब्जेक्ट्स को लिखने का आविष्कार करने की अनुमति नहीं है।

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

लेकिन अगर संकलक जानता है कि एक वस्तु हमेशा लिखी जाती है, तो वह जो कुछ भी चाहता है वह काफी कुछ कर सकता है क्योंकि एक कानूनी कार्यक्रम अंतर नहीं देख सकता है: इसमें डेटा-रेस यूबी शामिल होगा।


थोड़ा और विशेष रूप से, क्या प्रोसेसर सट्टा लेखन को निष्पादित कर सकता है (जब स्थिति अंततः झूठी का मूल्यांकन करेगी), एक और धागा लेखन को होने के रूप में देखता है, और फिर पहला धागा सट्टा लेखन को छोड़ देता है?

नहीं, अटकलबाजी करने से अटकलें नहीं निकलती हैं। अन्यथा जब गलत अटकलों का पता चलता है, तो सभी कोर को अपनी स्थिति वापस लेनी होगी!

यह स्टोर बफ़र्स के मौजूद होने के प्राथमिक कारणों में से एक है: OoO सट्टा निष्पादन स्टोर्स को प्रतिबद्ध से L1d कैश में अलग करना (जो तब होता है जब स्टोर अन्य कोर के लिए विश्व स्तर पर दृश्यमान हो जाता है) ) और कैश-मिस स्टोर से निष्पादन को अलग करने के लिए जो इन-ऑर्डर गैर-सट्टा सीपीयू पर भी उपयोगी है।

स्टोर निर्देश आउट-ऑफ-ऑर्डर कोर (यानी गैर-सट्टा के रूप में जाना जाता है) से स्टोर निर्देश सेवानिवृत्त होने तक स्टोर L1d के लिए प्रतिबद्ध नहीं होते हैं। सेवानिवृत्त स्टोर जो अभी तक प्रतिबद्ध नहीं हैं, उन्हें कभी-कभी "स्नातक" कहा जाता है ताकि उन्हें अन्य स्टोर-बफर प्रविष्टियों से अलग किया जा सके, जिन्हें संभावित रूप से त्याग दिया जा सकता है यदि कोर को सेवानिवृत्ति की स्थिति में वापस रोल करने की आवश्यकता होती है।

यह लेखन का आविष्कार किए बिना हार्डवेयर सट्टा निष्पादन की अनुमति देता है।

(यह भी देखें क्या एक सट्टा निष्पादित CPU शाखा में शामिल हो सकता है अधिक विवरण के लिए ऑपकोड?। मजेदार तथ्य: कुछ सीपीयू, विशेष रूप से पावरपीसी, एक ही भौतिक कोर पर एसएमटी थ्रेड्स के बीच स्नातक किए गए स्टोरों को स्टोर-अग्रेषण कर सकते हैं, जिससे स्टोर कुछ कोर के लिए दृश्यमान हो जाते हैं विश्व स्तर पर दिखाई दे रहा है। लेकिन केवल स्नातक किए गए स्टोर के लिए, अन्यथा संभव गलत अटकलें लीक हो सकती हैं।)


C++ में, एक std::mo_release स्टोर कंपाइलर को पर्याप्त बाधाओं या रिलीज-स्टोर निर्देशों का उपयोग करने के लिए मजबूर करता है (उदाहरण के लिए x86 पर एक सामान्य mov एक रिलीज-स्टोर है, या stlr AArch64 पर एक अनुक्रमिक है -रिलीज स्टोर)। या जो भी अन्य तंत्र यह सुनिश्चित करने के लिए कि एएसएम रनटाइम ऑर्डरिंग की गारंटी देता है कम से कम उतना ही मजबूत है जितना कि C++ एब्स्ट्रैक्ट मशीन गारंटी।

सी ++ अनुक्रमित-पहले/बाद में, बाधाओं के संदर्भ में अपने मानक को परिभाषित करता है, लेकिन किसी दिए गए प्लेटफ़ॉर्म कार्यान्वयन/एबीआई मानकीकरण पर std :: परमाणु संचालन से एएसएम अनुक्रमों तक कुछ मैपिंग पर मानकीकृत करता है। (उदाहरण के लिए https://www.cl.cam.ac.uk /~pes20/cpp/cpp0xmappings.html)

6
Peter Cordes 16 अप्रैल 2021, 21:12