2011-07-05 6 views
12

एसटीडी है :: random_shuffle threadsafe? मुझे लगता है कि नियमित रैंड() थ्रेडसेफ नहीं है। यदि ऐसा है, तो मैं random_shuffle के साथ rand_r का उपयोग कैसे करूं ताकि मैं प्रत्येक थ्रेड को एक अद्वितीय बीज दे सकूं। मैंने random_shuffle के साथ कस्टम यादृच्छिक जेनरेटर का उपयोग करने के उदाहरण देखे हैं, लेकिन यह अभी भी मेरे लिए अस्पष्ट है।क्या random_shuffle threadsafe है? और rand_r का उपयोग कर अगर यह नहीं है

धन्यवाद।

+4

आम तौर पर आप इस धारणा है कि * सी ++ पुस्तकालय में कुछ भी नहीं * है बनाना चाहिए थ्रेड-सुरक्षित जब तक दस्तावेज़ अन्यथा नहीं कहता है। –

+1

इसके अलावा, 'थ्रेडसेफ' एक बहुत अधिभारित शब्द है। कुछ एल्गोरिदम केवल तभी सुरक्षित होते हैं जब वे सुरक्षित डेटा पर काम करते हैं। कुछ तब तक सुरक्षित होते हैं जब तक केवल 1 लेखक ही नहीं होते हैं, और अधिकांश इसकी गारंटी नहीं दे सकते हैं। आम तौर पर, यह तय करते समय कि सुरक्षित क्या है (यानी सही), यह आवश्यक है कि आप विभिन्न पढ़ने/लिखने की आवश्यकताओं को निर्दिष्ट करें। – Kylotan

+0

बस स्पष्ट करने के लिए, मैं समानांतर में विभिन्न सूचियों पर शफल करना चाहता हूं।तो मैं डेटा संरचना में दौड़ के बारे में चिंतित नहीं हूं, केवल शफल के लिए यादृच्छिक संख्या की पीढ़ी। – Mark

उत्तर

4

std::random_shuffle साथ rand_r उपयोग करने के लिए, आप एक (काफी तुच्छ) आवरण लिखने के लिए की आवश्यकता होगी। यादृच्छिक संख्या जनरेटर आप random_shuffle के पास एक पैरामीटर निर्दिष्ट करता है कि संख्या की सीमा का उत्पादन किया जाना है, जो rand_r नहीं स्वीकार करने के लिए की जरूरत है।

आपका आवरण कुछ इस तरह दिखेगा:

class rand_x { 
    unsigned int seed; 
public: 
    rand_x(int init) : seed(init) {} 

    int operator()(int limit) { 
     int divisor = RAND_MAX/(limit+1); 
     int retval; 

     do { 
      retval = rand_r(&seed)/divisor; 
     } while (retval > limit); 

     return retval; 
    }   
}; 

आप random_shuffle कुछ तरह के साथ इसे उपयोग करेंगे:

std::random_shuffle(whatever.begin(), whatever.end(), rand_x(some_seed)); 
+0

धन्यवाद। बीज एक हस्ताक्षरित int होना चाहिए। इसके अलावा, rand_r (और बीज)% सीमा लौटने के विरोध में लूप के दौरान ऐसा क्यों होता है? क्या कुछ सूक्ष्म है जो मुझे याद आ रही है? – Mark

+0

@ मार्क: ओह - निश्चित। डू लूप के बारे में, इस बात पर विचार करें कि आप कैसे 3 बच्चों के बीच समान रूप से 10 कैंडीज विभाजित करते हैं (और आप टुकड़ों में एक कैंडी नहीं तोड़ सकते हैं)। जवाब यह है कि आप नहीं कर सकते - आप केवल उनमें से 9 वितरित कर सकते हैं। यह मूल रूप से 'सीमा' बच्चों के बीच 'RAND_MAX' कैंडी को विभाजित करने और किसी भी बाएं ओवर को हटाने के लिए एक ही चीज़ कर रहा है, इसलिए सभी ढेर बराबर हैं। '% सीमा' (या'/divisor') का उपयोग करके * * संख्याओं को समान रूप से विभाजित नहीं कर सकता है जब तक कि 'RAND_MAX' 'सीमा' का सटीक एकाधिक न हो (और' RAND_MAX' अक्सर प्राइम होता है, इसलिए यह एक नहीं है * किसी भी * सार्थक 'सीमा' के सटीक बहु)। –

+0

हालांकि मैं जैरी ने जो भी कहा है, उससे सहमत हूं, लेकिन कोई तर्क दे सकता है कि यदि आप 'rand_r' का उपयोग कर रहे हैं, तो आप यह मानने के हकदार नहीं हैं कि इसे संरक्षित करने के लिए एक समान वितरण है। लेकिन कम से कम इस तरह, * अगर * 'rand_r' अच्छा है, तो आपका शफल भी अच्छा है, आप किसी भी नए पूर्वाग्रह को पेश नहीं कर रहे हैं। –

3

आपको एक यादृच्छिक संख्या जनरेटर फ़ंक्शन या फ़ैक्टर ऑब्जेक्ट प्रदान करने की आवश्यकता है जो एक अभिन्न मूल्य प्रकार लेता है और कुछ अभिन्न प्रकार का एक और मान देता है जो कंटेनर की सीमाओं को ओवरफ़्लो नहीं करेगा जो आपके द्वारा फ़ंक्शन में पारित किए गए इटरेटर हैं के माध्यम से पुनरावृत्त इसके अलावा एक functor वस्तु के मामले में, यह operator() को लागू करना चाहिए ताकि यह एक समारोह की तरह कहा जा सकता है। क्योंकि आप एक धागा सुरक्षित यादृच्छिक संख्या जनरेटर की जरूरत है, एक बुरा विचार cstdlib से srand और rand उपयोग कर रहा है ... आप के बजाय कुछ functor वस्तु है कि एक धागा सुरक्षित यादृच्छिक संख्या जनरेटर को लागू करता है, या एक यादृच्छिक संख्या जनरेटर बनाने चाहिए कि विश्व स्तर पर सुलभ चर लागू नहीं करता है ताकि सब कुछ धागा-स्थानीय भंडारण बनी रहे।

तो उदाहरण के लिए, यह एक तरीका यह काम कर सकता है कि आपके पास कुछ अन्य प्रकार की यादृच्छिक संख्या जेनरेटर है जो आपको किसी अन्य लाइब्रेरी से प्राप्त हुआ है जो केवल मूल्यों की एक निश्चित सीमा के बीच यादृच्छिक मान उत्पन्न करेगा ताकि आप कंटेनर की सीमाओं को परिभाषित कर सकें यादृच्छिक-पहुंच इटरेटर्स के लिए random_shuffle एल्गोरिदम उपयोग करता है। अब क्या पुस्तकालय आप उपयोग पर निर्भर करता है, तो आप functor की तरह कुछ दिखाई दे सकता है निम्नलिखित:

class my_rand_gen 
{ 
    private: 
     random_gen_type random_range_gen; 
     int min; 
     int max; 

    public: 
     my_rand_gen(const random_gen_type& gen, int min_range, int max_range): 
        random_range_gen(gen), min(min_range), max(max_range) {} 

     int operator()(int value) 
     { 
      //ignore the input value and use our own defined range 
      //returns a value between min and max 
      return random_range_gen(min, max); 
     } 
}; 

अब आप की तरह एल्गोरिथ्म कॉल कर सकते हैं:

random_shuffle(my_vector_start_iter, my_vector_end_iter, 
       my_rand_gen(rand_generator_lib, 
          vector_start_index, 
          vector_end_index)); 

और यह शुरुआत के बीच में वेक्टर शफ़ल होगा और वेक्टर की सीमा ... दूसरे शब्दों में यह केवल vector_start_index और vector_end_index के बीच फेरबदल के लिए मूल्यों का उपयोग करेगा बह निकला बिना अपने वेक्टर को iterators खत्म।

+0

नया '' कक्षाएं इसके लिए अच्छी शुरुआत होगी - आपके पास हो सकता है प्रति धागा एक पीआरएनजी। –

1
शायद नहीं

adnrom_shuffle का दूसरा संस्करण उपयोग करें जो यादृच्छिक संख्या जनरेटर के लिए टेम्पलेट पैरामीटर लेता है: http://www.sgi.com/tech/stl/random_shuffle.html। जनरेटर से मेल खाना चाहिए: http://www.sgi.com/tech/stl/RandomNumberGenerator.html

struct MyRandomNumberGenerator 
{ 
    int operator()(int limit) const 
    { 
     // get threadsafe random number 
    } 
}; 

// Stuff 
random_shuffle(list.begin(), list.end(), MyRandomNumberGenerator()); 
संबंधित मुद्दे