2013-02-21 91 views
7

स्थिति जो मैं वर्णन करूंगा वह एक आईपैड 4 (एआरएमवी 7 एस) पर हो रहा है, जो म्यूटेक्स लॉक/अनलॉक पर पॉज़िक्स libs का उपयोग कर रहा है। मैंने अन्य एआरएमवी 7 उपकरणों पर समान चीजें देखी हैं, हालांकि (नीचे देखें), इसलिए मुझे लगता है कि किसी भी समाधान के लिए एआरएमवी 7 के लिए म्यूटेक्स और मेमोरी बाड़ के व्यवहार पर अधिक सामान्य रूप की आवश्यकता होगी।क्या mutex_unlock मेमोरी बाड़ के रूप में कार्य करता है?

void ProduceFunction() { 
    MutexLock(); 
    int TempProducerIndex = mSharedProducerIndex; // Take a copy of the int member variable for Producers Index 
    mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index 
    mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable 
    MutexUnlock(); 
} 

थ्रेड 2 - उपभोक्ता डेटा:

void ConsumingFunction() { 
    while (mConsumerIndex != mSharedProducerIndex) { 
    doWorkOnData (mSharedArray[mConsumerIndex++]); 
    } 
} 

पहले (जब समस्या क्रॉप - उत्पादन डाटा

थ्रेड 1:

छद्म परिदृश्य के लिए कोड आईपैड 2 पर), मुझे विश्वास था कि mSharedProducerIndex = TempProducerIndex परफ नहीं किया जा रहा था परमाणु रूप से ormedically, और इसलिए का उपयोग mSharedProducerIndex असाइन करने के लिए बदल गया। इस बिंदु तक यह काम कर चुका है, लेकिन यह पता चला कि मैं गलत था और बग वापस आ गया है। मुझे लगता है कि 'फिक्स' बस कुछ समय बदल गया।

मैं अब निष्कर्ष यह है कि वास्तविक समस्या म्युटेक्स लॉक, यानी भीतर लेखन के आदेश निष्पादन के बाहर है अगर या तो संकलक या हार्डवेयर को पुन: व्यवस्थित करने का निर्णय लिया के लिए आए हैं:

mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index 
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable 

.. । के लिए:

mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable 
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index 

... और फिर उपभोक्ता निर्माता interleaved, डेटा अभी तक नहीं लिखा है | किया गया जब उपभोक्ता इसे पढ़ने की कोशिश की।

स्मृति बाधाओं पर कुछ पढ़ने के बाद, मैं इसलिए सोचा कि मैं करने के लिए लिखा गया था mutex_unlock बाहर उपभोक्ता के लिए संकेत ले जाने का प्रयास करना चाहते हैं, उनका मानना ​​है कि अनलॉक एक स्मृति बाधा/बाड़ जो mSharedArray यह सुनिश्चित करना होगा उत्पादन होगा:

mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index 
MutexUnlock(); 
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable 

हालांकि, यह अभी भी विफल रहता है, और मुझे प्रश्न पूछता है कि mutex_unlock निश्चित रूप से एक लिखने की बाड़ के रूप में कार्य करेगा या नहीं?

मैं भी an article from HP पढ़ा है जो सुझाव दिया है कि compilers (लेकिन बाहर के) crit_sec रों में कोड को स्थानांतरित कर सकते हैं। तो उपरोक्त परिवर्तन के बाद भी, mSharedProducerIndex का लेखन बाधा से पहले हो सकता है। क्या इस सिद्धांत के लिए कोई लाभ है?

एक स्पष्ट बाड़ को जोड़ कर समस्या दूर हो जाने:

mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index 
OSMemoryBarrier(); 
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable 

इसलिए मैं लगता है कि मैं इस समस्या को समझने, और कहा कि एक बाड़ आवश्यक है, लेकिन अनलॉक के व्यवहार में किसी भी अंतर्दृष्टि और कारण है कि यह 'नहीं करता है एक बाधा प्रदर्शन करने के लिए प्रतीत होता है वास्तव में उपयोगी होगा।

संपादित करें:

उपभोक्ता सूत्र में एक म्युटेक्स की कमी के बारे में: मैं उम्मीद कर रहा उपभोक्ता या तो नए या पुराने मूल्य पढ़ें एक एकल अनुदेश जा रहा है int mSharedProducerIndex के लिखने पर भरोसा कर रहा हूँ और इसलिए । या तो मान्य राज्य हैं, और mSharedArray प्रदान करना अनुक्रम में लिखा गया है (यानी।mSharedProducerIndex लिखने से पहले) यह ठीक रहेगा, लेकिन अब तक जो कहा गया है, उससे मैं इसका जवाब नहीं दे सकता।

यही तर्क ऐसा लगता है कि वर्तमान बाधा समाधान भी त्रुटिपूर्ण के रूप में mSharedProducerIndex लिखने बाधा के अंदर ले जाया जा सकता है और इसलिए संभवतः गलत तरीके से फिर से आदेश दिया जा सकता है के द्वारा।

क्या यह केवल पढ़ने के लिए बाधा के रूप में कार्य करने के लिए उपभोक्ता को म्यूटेक्स जोड़ने की सिफारिश की जाती है, या क्या pragma या पीपीसी पर EIEIO जैसे निर्माता पर आउट ऑफ़ ऑर्डर निष्पादन को अक्षम करने के लिए निर्देश है?

+2

स्टीव सुझाव के अनुसार, आप * पढ़ने * * mSharedProducerIndex' के तुरंत बाद OSMemoryBarrier() कर सकते हैं। पिछले परीक्षण से पता चला है कि OSMemoryBarrier() OSSpinLockLock + अनलॉक() से कुछ हद तक तेज था जो pthread mutexes से बहुत तेज था। –

उत्तर

5

आपके उत्पाद सिंक किए गए हैं लेकिन आप उपभोग करने पर किसी भी सिंक्रनाइज़ेशन (आपको बाधाओं के साथ स्मृति को सिंक्रनाइज़ करने की आवश्यकता नहीं है) नहीं करते हैं। इसलिए यदि आपके पास उत्पादकों के लिए सही स्मृति बाधाएं हैं कि स्मृति बाधाएं उपभोक्ताओं की सहायता नहीं करती हैं।

अपने कोड में, आप कंप्रेसर के ऑर्डरिंग, हार्डवेयर ऑर्डरिंग को mSharedProducerIndex के अन्य मूल चल रहे थ्रेड # 2 पर भी दबा सकते हैं।

आपको Cortex™-A Series Programmer’s Guide से, विशेष रूप से 11.2.1 Memory barrier use example से पढ़ना चाहिए।

मुझे लगता है कि आपकी समस्या यह है कि आपको उपभोक्ता धागे में आंशिक अपडेट मिल रहे हैं। उत्पादक में महत्वपूर्ण खंड के अंदर समस्या यह है कि परमाणु नहीं है और इसे फिर से व्यवस्थित किया जा सकता है।

not atomic से मेरा मतलब है अगर आपके mSharedArray[TempProducerIndex++] = NewData; एक शब्द की दुकान (NewData पूर्णांक के प्रकार है) यह कई कदम है जो अन्य कोर के रूप में आंशिक अपडेट करके देखा जा सकता में किया जा सकता है नहीं है।

reordering मेरा मतलब है कि म्यूटेक्स बाधाओं को बाहर और बाहर प्रदान करता है लेकिन महत्वपूर्ण अनुभाग के दौरान कोई ऑर्डर नहीं लगाता है। चूंकि आपके पास उपभोक्ता पक्ष में कोई विशेष निर्माण नहीं है, इसलिए आप mSharedProducerIndex अपडेट कर सकते हैं लेकिन अभी भी mSharedArray[mConsumerIndex] पर आंशिक अपडेट देख सकते हैं। निष्पादन महत्वपूर्ण खंड छोड़ने के बाद म्यूटेक्स केवल स्मृति दृश्यता की गारंटी देता है।

मेरा मानना ​​है कि यह भी बताता है कि क्यों यह है जब आप महत्वपूर्ण अनुभाग के अंदर OSMemoryBarrier(); जोड़ने के लिए, क्योंकि इस तरह से सीपीयू और mSharedArray में डेटा लिखने के लिए तो mConsumerIndex अद्यतन मजबूर किया जाता है जब अन्य कोर/धागा mConsumerIndex देखता है हम जानते हैं कि mSharedArray पूरी तरह से क्योंकि कॉपी किया जाता है काम करता है बाधा का

मुझे लगता है कि OSMemoryBarrier(); के साथ आपका कार्यान्वयन सही है कि आपके पास कई उत्पादक और एक उपभोक्ता हैं। उपभोक्ता में मेमोरी बाधा डालने का सुझाव देने वाली किसी भी टिप्पणी से मैं असहमत हूं, क्योंकि मेरा मानना ​​है कि आंशिक अपडेट या पुनर्वितरण को निर्माता के अंदर महत्वपूर्ण खंड में नहीं किया जाएगा।

शीर्षक में आपके प्रश्न के उत्तर के रूप में, सामान्य afaik mutex es में प्रवेश करने से पहले बाधा पढ़ने और लिखने से पहले बाधा पढ़ती है।

+0

अब तक आपके इनपुट के लिए धन्यवाद, मैंने इस सवाल को संपादित किया है जिसे उम्मीद है कि इसे थोड़ा सा स्पष्ट करना चाहिए। – sjwarner

+0

@sjwarner ने मेरा जवाब अपडेट किया। – auselen

+0

@sjwarner अगर mSharedArray चींटियों की एक सरणी नहीं है, तो मुझे लगता है कि आपको अभी भी दृश्यता की समस्याएं हो सकती हैं, इसलिए मैं आपको सलाह देता हूं कि आप उपभोक्ता थ्रेड में पढ़ने की बाधा डालें - बस लूप की शुरुआत में। यह संभव हो सकता है कि कोर का कैश अपडेट करने की प्रक्रिया में है और आप इसके लिए इंतजार नहीं करेंगे - जैसा कि एक पढ़ा गया बाधा है। – auselen

5

"सिद्धांत" सही है, लिखने से पहले लिखने वाली बाड़ के बाद से लिखा जा सकता है।

आपके कोड के साथ मौलिक समस्या यह है कि थ्रेड 2 में कोई सिंक्रनाइज़ेशन नहीं है। आप पढ़े गए बाधा के बिना mSharedProducerIndex पढ़ते हैं, तो कौन जानता है कि आपको कौन सा मूल्य मिलेगा। थ्रेड 1 में आप जो कुछ भी करते हैं वह हल नहीं करेगा।

+0

क्षमाप्रार्थी, मैंने अपने छद्म कोड को बढ़ा दिया है, एक सेकंड में एक संपादन कर देगा। हालांकि, जवाब के लिए चीयर्स। – sjwarner

+0

संपादित किया गया, उम्मीद है कि यह स्थिति को स्पष्ट करता है। चीयर्स :) – sjwarner