क्या रूबी में असली मल्टीथ्रेडिंग है?


295

मुझे पता है कि "सहकारी" हरे धागे का उपयोग करके माणिक के बारे में सोच रहा था । मैं प्रसंस्करण के लिए कई सीपीयू कोर का उपयोग करने के लिए अपने आवेदन में वास्तविक "ओएस-स्तर" धागे कैसे बना सकता हूं?

जवाबों:


612

Jörg के सितंबर 2011 की टिप्पणी के साथ अपडेट किया गया

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

(दुर्भाग्य से, उन 11 में से केवल दो कार्यान्वयन वास्तव में उत्पादन उपयोग के लिए तैयार हैं, लेकिन वर्ष के अंत तक यह संख्या संभवतः चार या पांच हो जाएगी।) ( अपडेट : यह अब 5 है: एमआरआई, जुआरबी, यारव (दुभाषिया) रूबी 1.9 के लिए), रुबिनियस और आयरनरबी)।

  1. पहले कार्यान्वयन में वास्तव में एक नाम नहीं है, जो इसे संदर्भित करने के लिए काफी अजीब बनाता है और वास्तव में कष्टप्रद और भ्रमित है। इसे अक्सर "रूबी" के रूप में संदर्भित किया जाता है, जो बिना नाम लिए भी अधिक कष्टप्रद और भ्रामक है, क्योंकि यह रूबी प्रोग्रामिंग भाषा और एक विशेष रूप से रूबी कार्यान्वयन की सुविधाओं के बीच अंतहीन भ्रम की ओर जाता है।

    इसे कभी-कभी "एमआरआई" ("मैट्स रूबी इम्प्लीमेंटेशन"), क्रुबी या मैटज़ुर्बी भी कहा जाता है।

    एमआरआई रूबी थ्रेड्स को अपने दुभाषिया के भीतर ग्रीन थ्रेड के रूप में लागू करता है । दुर्भाग्य से, यह उन थ्रेड्स को समानांतर में शेड्यूल करने की अनुमति नहीं देता है, वे केवल एक समय में एक धागा चला सकते हैं।

    हालांकि, सी थ्रेड्स (पोसिक्स थ्रेड्स) की कोई भी संख्या रूबी थ्रेड के समानांतर चल सकती है, इसलिए बाहरी सी लाइब्रेरी, या एमआरआई सी एक्सटेंशन्स जो स्वयं के थ्रेड बनाते हैं, वे अभी भी समानांतर में चल सकते हैं।

  2. दूसरा कार्यान्वयन YARV ("फिर भी एक और रूबी VM" के लिए छोटा है)। YARV रूबी थ्रेड्स को POSIX या Windows NT थ्रेड्स के रूप में लागू करता है, हालांकि, यह सुनिश्चित करने के लिए एक ग्लोबल इंटरप्रेटर लॉक (GIL) का उपयोग करता है कि केवल एक रूबी थ्रेड को वास्तव में किसी एक समय पर शेड्यूल किया जा सकता है।

    एमआरआई की तरह, सी थ्रेड्स वास्तव में रूबी थ्रेड्स के समानांतर चल सकते हैं

    भविष्य में, यह है कि जीआईएल संभव है, हो सकता है अधिक परिष्कृत ताले में टूट जाते हैं, इस प्रकार अधिक है और वास्तव में समानांतर में चलाने के लिए और अधिक कोड अनुमति देता है, लेकिन यह है कि, अब तक दूर है तो यह और भी नहीं है की योजना बनाई अभी तक।

  3. JRuby रूबी थ्रेड्स को मूल धागे के रूप में लागू करता है , जहां JVM के मामले में "मूल धागे" का स्पष्ट अर्थ "JVM थ्रेड्स" है। JRuby उन पर कोई अतिरिक्त लॉकिंग नहीं लगाता है। तो, क्या वे धागे वास्तव में समानांतर में चल सकते हैं, जेवीएम पर निर्भर करता है: कुछ जेवीएम जेवीएम थ्रेड्स को ओएस थ्रेड्स के रूप में और कुछ ग्रीन थ्रेड्स के रूप में लागू करते हैं। (सन / ओरेकल से मुख्यधारा JVM JDK 1.3 के बाद से विशेष रूप से OS थ्रेड्स का उपयोग करते हैं)

  4. XRuby रूबी थ्रेड्स को JVM थ्रेड्स के रूप में भी लागू करता हैअद्यतन : XRuby मर चुका है।

  5. आयरनरुबी रूबी थ्रेड्स को मूल धागे के रूप में लागू करता है , जहां सीएलआर के मामले में "मूल धागे" का स्पष्ट अर्थ है "सीएलआर थ्रेड्स"। आयरनरुबी उन पर कोई अतिरिक्त लॉकिंग नहीं लगाता है, इसलिए, उन्हें समानांतर में चलना चाहिए, जब तक कि आपका सीएलआर समर्थन नहीं करता है।

  6. Ruby.NET भी CLR थ्रेड्स के रूप में रूबी थ्रेड्स को लागू करता हैअद्यतन: Ruby.NET मर चुका है।

  7. रुबिनस रूबी थ्रेड्स को अपने वर्चुअल मशीन के भीतर ग्रीन थ्रेड्स के रूप में लागू करता है । अधिक सटीक रूप से: रुबिनियस वीएम एक बहुत ही हल्के, बहुत लचीले कंसिस्टेंसी / समानांतरवाद / गैर-स्थानीय नियंत्रण-प्रवाह निर्माण का निर्यात करता है, जिसे " टास्क " कहा जाता है , और अन्य सभी संगामिति निर्माण (इस चर्चा में धागे, लेकिन निरंतरता , अभिनेता और अन्य सामान भी हैं। ) टास्क का उपयोग करके शुद्ध रूबी में लागू किया जाता है।

    रुबिनियस समानांतर में थ्रेड्स (वर्तमान में) शेड्यूल नहीं कर सकता है, हालांकि, यह जोड़ना एक समस्या का बहुत अधिक नहीं है: रुबिनियस पहले से ही एक पॉलीनिक्स प्रक्रिया में कई पोस्मिक्स थ्रेड्स में कई वीएम उदाहरणों को एक रुबिनस प्रक्रिया के भीतर चला सकता है। चूंकि थ्रेड्स वास्तव में रूबी में लागू होते हैं, इसलिए वे किसी भी अन्य रूबी ऑब्जेक्ट की तरह धारावाहिक हो सकते हैं और एक अलग VM में एक अलग POSIX थ्रेड में भेजे जा सकते हैं। (यह वही मॉडल है जो BEAM Erlang VM SMP कॉनक्यूरेन्सी के लिए उपयोग करता है। यह रुबिनियस एक्टर्स के लिए पहले से ही लागू है ।)

    अद्यतन : इस उत्तर में रुबिनियस के बारे में जानकारी शॉटगन वीएम के बारे में है, जो अब मौजूद नहीं है। "नया" सी ++ वीएम कई वीएम (यानी एरलेंग / बीईएम शैली) में निर्धारित हरे रंग के धागे का उपयोग नहीं करता है, यह एक अधिक पारंपरिक एकल वीएम का उपयोग करता है जिसमें कई देशी ओएस थ्रेड्स मॉडल होते हैं, जैसे कि सीएलआर, मोनो द्वारा नियोजित , और बहुत ज्यादा हर JVM।

  8. MacRuby ने Y -V के पोर्ट के रूप में ऑब्जेक्टिव-सी रनटाइम और कोरफाउंडेशन और कोको फ्रेमवर्क के शीर्ष पर शुरुआत की। यह अब YARV से महत्वपूर्ण रूप से अलग हो गया है, लेकिन AFAIK अभी भी YARV के साथ एक ही थ्रेडिंग मॉडल साझा करता हैअद्यतन: MacRuby सेब कचरा कलेक्टर पर निर्भर करता है जिसे पदावनत घोषित किया जाता है और MacOSX के बाद के संस्करणों में हटा दिया जाएगा, MacRuby पूर्ववत है।

  9. कार्डिनल तोता वर्चुअल मशीन के लिए एक रूबी कार्यान्वयन है । यह धागे को अभी तक लागू नहीं करता है, हालांकि, जब यह करता है, तो यह संभवतः उन्हें तोता धागे के रूप में लागू करेगा । अपडेट : कार्डिनल बहुत निष्क्रिय / मृत लगता है।

  10. मैग्लेव के लिए एक रूबी कार्यान्वयन है रत्न / एस स्मालटाक वीएम । मुझे कोई जानकारी नहीं है कि थ्रेडिंग मॉडल जेमस्टोन / एस का उपयोग करता है, थ्रेडिंग मॉडल मैगलेव का उपयोग करता है या यहां तक ​​कि अगर थ्रेड को अभी भी लागू किया जाता है (शायद नहीं)।

  11. Hotruby है नहीं अपने आप में एक पूर्ण रूबी क्रियान्वयन। यह जावास्क्रिप्ट में एक YARV bytecode VM का कार्यान्वयन है। HotRuby थ्रेड्स (अभी तक?) का समर्थन नहीं करता है और जब ऐसा होता है, तो वे समानांतर में नहीं चल पाएंगे, क्योंकि जावास्क्रिप्ट में सच्चे समानता के लिए कोई समर्थन नहीं है। हालांकि, HotRuby का एक एक्शनस्क्रिप्ट संस्करण है, और एक्शनस्क्रिप्ट वास्तव में समानता का समर्थन कर सकता है। अद्यतन : HotRuby मर चुका है।

दुर्भाग्य से, इन 11 रूबी कार्यान्वयन में से केवल दो वास्तव में उत्पादन-तैयार हैं: एमआरआई और जेरी।

इसलिए, यदि आप सच्चे समानांतर धागे चाहते हैं, तो JRuby वर्तमान में आपकी एकमात्र पसंद है - ऐसा नहीं है कि यह एक बुरा है: JRuby वास्तव में एमआरआई से तेज है, और यकीनन अधिक स्थिर है।

अन्यथा, "शास्त्रीय" रूबी समाधान समानांतरवाद के लिए थ्रेड्स के बजाय प्रक्रियाओं का उपयोग करना है। रूबी मुख्य लाइब्रेरी शामिल Processमॉड्यूल के साथ Process.fork विधि है जो इसे मृत आसान बंद एक और रूबी प्रक्रिया कांटा करने के लिए बनाता है। इसके अलावा, रूबी स्टैण्डर्ड लाइब्रेरी में डिस्ट्रीब्यूटेड रूबी (dRuby / dRb) लाइब्रेरी शामिल है, जो न केवल एक ही मशीन पर बल्कि पूरे नेटवर्क में रूबी कोड को कई प्रक्रियाओं में तुच्छ रूप से वितरित करने की अनुमति देती है।


1
लेकिन कांटा का उपयोग करने पर तोड़
फोड़ का

1
यह एक बेहतरीन जवाब है। हालाँकि यह बहुत सारे लिंक रोट के अधीन है। मैं नहीं जानता कि ये संसाधन कहाँ स्थानांतरित हो सकते हैं।
ब्लैकवेटेबल

28

रूबी 1.8 में केवल हरे रंग के धागे हैं, असली "ओएस-स्तर" धागा बनाने का कोई तरीका नहीं है। लेकिन, रूबी 1.9 में फाइबर नामक एक नई सुविधा होगी, जो आपको वास्तविक ओएस-स्तर के धागे बनाने की अनुमति देगा। दुर्भाग्य से, रूबी 1.9 अभी भी बीटा में है, यह कुछ महीनों में स्थिर होना निर्धारित है।

JRuby का उपयोग करने के लिए एक और विकल्प है। JRuby OS- स्तर के थ्रेड्स के रूप में थ्रेड को लागू करता है, इसमें कोई "ग्रीन थ्रेड" नहीं हैं। JRuby का नवीनतम संस्करण 1.1.4 है और यह रूबी 1.8 के बराबर है


35
यह गलत है कि रूबी 1.8 में केवल हरे रंग के धागे हैं, रूबी 1.8 के कई कार्यान्वयन में मूल धागे हैं: जेरी, एक्सुबी, रूबी.नेट और आयरनरुबी। रेशे देशी धागे के निर्माण की अनुमति नहीं देते हैं, वे धागे की तुलना में अधिक हल्के होते हैं। वे वास्तव में अर्ध-कोराउटाइन हैं, अर्थात वे सहकारी हैं।
जोर्ग डब्ल्यू मित्तग

19
मुझे लगता है कि यह जोश के जवाब से बहुत स्पष्ट है कि वह रूबी 1.8 रनटाइम, उर्फ ​​एमआरआई, और रूबी 1.8 नहीं भाषा का मतलब है, जब वह रूबी 1.8 कहता है।
थियो

@ यह भी स्पष्ट है कि वह अपने उत्तर में अवधारणाओं को गड़बड़ कर रहा है। रेशे देशी धागे बनाने का एक तरीका नहीं हैं, जैसा कि पहले ही उल्लेख किया गया है, वे धागे की तुलना में अधिक हल्की चीजें हैं और वर्तमान क्रुबी में देशी धागे हैं लेकिन जीआईएल के साथ।
फू बार चिड़ियाघर 19

8

यह कार्यान्वयन पर निर्भर करता है:

  • MRI नहीं है, YARV करीब है।
  • JRuby और MacRuby है।




रूबी के पास क्लोजर है Blocks, lambdasऔर Procs। JRuby में बंद और कई कोर का पूरा लाभ उठाने के लिए, जावा के निष्पादक काम में आते हैं; MacRuby के लिए मुझे GCD की कतारें पसंद हैं ।

ध्यान दें कि, वास्तविक "OS-level" थ्रेड बनाने में सक्षम है नहीं है कि आप समानांतर प्रसंस्करण के लिए कई सीपीयू कोर का उपयोग कर सकते हैं। नीचे दिए गए उदाहरण देखें।

यह एक साधारण रूबी प्रोग्राम का आउटपुट है जो रूबी 2.1.0 का उपयोग करके 3 थ्रेड का उपयोग करता है :

(jalcazar@mac ~)$ ps -M 69877
USER     PID   TT   %CPU STAT PRI     STIME     UTIME COMMAND
jalcazar 69877 s002    0.0 S    31T   0:00.01   0:00.04 /Users/jalcazar/.rvm/rubies/ruby-2.1.0/bin/ruby threads.rb
   69877         0.0 S    31T   0:00.01   0:00.00 
   69877        33.4 S    31T   0:00.01   0:08.73 
   69877        43.1 S    31T   0:00.01   0:08.73 
   69877        22.8 R    31T   0:00.01   0:08.65 

जैसा कि आप यहां देख सकते हैं, चार ओएस थ्रेड हैं, हालांकि केवल एक राज्य के साथ Rचल रहा है। यह एक सीमा के कारण है कि रूबी के धागे कैसे लागू होते हैं।



एक ही कार्यक्रम, अब JRuby के साथ। आप राज्य के साथ तीन धागे देख सकते हैं R, जिसका अर्थ है कि वे समानांतर में चल रहे हैं।

(jalcazar@mac ~)$ ps -M 72286
USER     PID   TT   %CPU STAT PRI     STIME     UTIME COMMAND
jalcazar 72286 s002    0.0 S    31T   0:00.01   0:00.01 /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java -Djdk.home= -Djruby.home=/Users/jalcazar/.rvm/rubies/jruby-1.7.10 -Djruby.script=jruby -Djruby.shell=/bin/sh -Djffi.boot.library.path=/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jni:/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jni/Darwin -Xss2048k -Dsun.java.command=org.jruby.Main -cp  -Xbootclasspath/a:/Users/jalcazar/.rvm/rubies/jruby-1.7.10/lib/jruby.jar -Xmx1924M -XX:PermSize=992m -Dfile.encoding=UTF-8 org/jruby/Main threads.rb
   72286         0.0 S    31T   0:00.00   0:00.00 
   72286         0.0 S    33T   0:00.00   0:00.00 
   72286         0.0 S    31T   0:00.09   0:02.34 
   72286         7.9 S    31T   0:00.15   0:04.63 
   72286         0.0 S    31T   0:00.00   0:00.00 
   72286         0.0 S    31T   0:00.00   0:00.00 
   72286         0.0 S    31T   0:00.00   0:00.00 
   72286         0.0 S    31T   0:00.04   0:01.68 
   72286         0.0 S    31T   0:00.03   0:01.54 
   72286         0.0 S    31T   0:00.00   0:00.00 
   72286         0.0 S    31T   0:00.01   0:00.01 
   72286         0.0 S    31T   0:00.00   0:00.01 
   72286         0.0 S    31T   0:00.00   0:00.03 
   72286        74.2 R    31T   0:09.21   0:37.73 
   72286        72.4 R    31T   0:09.24   0:37.71 
   72286        74.7 R    31T   0:09.24   0:37.80 


एक ही कार्यक्रम, अब MacRuby के साथ। समानांतर में चलने वाले तीन धागे भी हैं। इसका कारण यह है कि MacRuby थ्रेड्स POSIX थ्रेड्स ( वास्तविक "OS-लेवल" थ्रेड्स ) हैं और कोई GVL नहीं है

(jalcazar@mac ~)$ ps -M 38293
USER     PID   TT   %CPU STAT PRI     STIME     UTIME COMMAND
jalcazar 38293 s002    0.0 R     0T   0:00.02   0:00.10 /Users/jalcazar/.rvm/rubies/macruby-0.12/usr/bin/macruby threads.rb
   38293         0.0 S    33T   0:00.00   0:00.00 
   38293       100.0 R    31T   0:00.04   0:21.92 
   38293       100.0 R    31T   0:00.04   0:21.95 
   38293       100.0 R    31T   0:00.04   0:21.99 


एक बार फिर, वही कार्यक्रम लेकिन अब अच्छे पुराने एमआरआई के साथ। इस तथ्य के कारण कि यह कार्यान्वयन हरे-धागे का उपयोग करता है, केवल एक धागा दिखाता है

(jalcazar@mac ~)$ ps -M 70032
USER     PID   TT   %CPU STAT PRI     STIME     UTIME COMMAND
jalcazar 70032 s002  100.0 R    31T   0:00.08   0:26.62 /Users/jalcazar/.rvm/rubies/ruby-1.8.7-p374/bin/ruby threads.rb



यदि आप रूबी मल्टी-थ्रेडिंग में रुचि रखते हैं तो आपको मेरी रिपोर्ट मिल सकती है कांटा हैंडलर का उपयोग करते हुए समानांतर प्रोग्राम डिबगिंग दिलचस्प।
रूबी इंटर्नल के एक अधिक सामान्य अवलोकन के लिए रूबी अंडर अ माईक्रोस्कोप एक अच्छा पढ़ा है।
इसके अलावा, रूबी थ्रेड्स और ओम्निरेफ में ग्लोबल इंटरप्रेटर लॉक इन सोर्स कोड में बताते हैं कि रूबी थ्रेड समानांतर में क्यों नहीं चलते हैं।


RMI द्वारा, आपका मतलब है MRI?
मयूरेश श्रीवास्तव

4

ड्रब का उपयोग कैसे करें ? यह वास्तविक मल्टी-थ्रेडिंग नहीं है, लेकिन कई प्रक्रियाओं के बीच संचार है, लेकिन आप इसे अब 1.8 में उपयोग कर सकते हैं और यह काफी कम घर्षण है।


3

मैं "सिस्टम मॉनिटर" को इस प्रश्न का उत्तर दूंगा। मैं एक ही कोड निष्पादित कर रहा हूं (नीचे, जो प्राइम संख्या की गणना करता है) दोनों मामलों में एक i7 (4 हाइपरथ्रेड-कोर) मशीन पर चलने वाले 8 रूबी थ्रेड्स के साथ ... पहला रन इसके साथ है:

jruby 1.5.6 (रूबी 1.8.7 पैचवेल 249) (2014-02-03 6586) (OpenJDK 64-बिट सर्वर VM 1.7.0_75) [amd64-java]

दूसरा साथ है:

माणिक 2.1.2p95 (2014-05-08) [x86_64-linux-gnu]

दिलचस्प है, सीपीयू JRuby थ्रेड्स के लिए अधिक है, लेकिन पूरा होने का समय रूबी की व्याख्या के लिए थोड़ा कम है। ग्राफ़ से यह बताना मुश्किल है, लेकिन दूसरा (रूबी के अनुसार) रन का उपयोग लगभग 1/2 सीपीयू (कोई हाइपरथ्रेडिंग नहीं है?) करता है।

यहां छवि विवरण दर्ज करें

def eratosthenes(n)
  nums = [nil, nil, *2..n]
  (2..Math.sqrt(n)).each do |i|
    (i**2..n).step(i){|m| nums[m] = nil}  if nums[i]
  end
  nums.compact
end

MAX_PRIME=10000000
THREADS=8
threads = []

1.upto(THREADS) do |num|
  puts "Starting thread #{num}"
  threads[num]=Thread.new { eratosthenes MAX_PRIME }
end

1.upto(THREADS) do |num|
    threads[num].join
end

1

यदि आप एमआरआई का उपयोग कर रहे हैं, तो आप सी में थ्रेडेड कोड को या तो विस्तार के रूप में लिख सकते हैं या रूबी-इनलाइन रत्न का उपयोग कर सकते हैं।


1

यदि आपको वास्तव में रूबी में उत्पादन स्तर प्रणाली (जहां आप बीटा को नियोजित नहीं कर सकते हैं) के लिए समानता की आवश्यकता है, तो प्रक्रियाएं शायद एक बेहतर विकल्प हैं।
लेकिन, यह सबसे निश्चित रूप से पहले JRuby के तहत धागे की कोशिश कर रहा लायक है।

अगर आप रूबी के तहत थ्रेडिंग के भविष्य में रुचि रखते हैं, तो आपको यह लेख उपयोगी लग सकता है।


JRuby एक अच्छा विकल्प है। प्रक्रियाओं का उपयोग करते हुए समानांतर प्रसंस्करण के लिए मुझे github.com/grosser/parallel Parallel.map(['a','b','c'], :in_processes=>3){...
user454322


1

क्योंकि वह उत्तर संपादित नहीं कर सका, इसलिए यहां एक नया उत्तर जोड़ें।

अद्यतन (2017/05/08)

यह लेख बहुत पुराना है, और जानकारी वर्तमान (2017) का पालन नहीं किया गया है, निम्नलिखित कुछ पूरक हैं:

  1. ओपल जावास्क्रिप्ट स्रोत से स्रोत संकलक के लिए एक रूबी है। इसमें रूबी कॉर्लिब का कार्यान्वयन भी है, यह वर्तमान बहुत सक्रिय विचलन है, और इस पर काम करने वाले (सामने वाले) ढांचे का एक बड़ा हिस्सा मौजूद है। और उत्पादन तैयार है। जावास्क्रिप्ट के आधार पर, यह समानांतर थ्रेड्स का समर्थन नहीं करता है।

  2. truffleruby रूबी प्रोग्रामिंग भाषा का एक उच्च प्रदर्शन कार्यान्वयन है। ओरेकल लैब्स द्वारा ग्रैल्वीएम पर निर्मित, ट्रूफ़्लेरुबी जेरीबी का एक कांटा है, इसे रुबिनियस परियोजना के कोड के साथ संयोजन किया गया है, और रूबी, एमआरआई के मानक कार्यान्वयन से कोड भी शामिल है, अभी भी लाइव विकास, उत्पादन तैयार नहीं है। यह संस्करण रूबी प्रदर्शन के लिए पैदा हुआ लगता है, मुझे नहीं पता कि समानांतर धागे का समर्थन है, लेकिन मुझे लगता है कि यह होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.