คำตอบ:
อัปเดตด้วยความคิดเห็นของJörgในเดือนกันยายน 2554
ดูเหมือนว่าคุณจะสับสนสองสิ่งที่แตกต่างกันมากที่นี่: ภาษาการเขียนโปรแกรมภาษาทับทิมและรูปแบบการทำเกลียวเฉพาะของการติดตั้งภาษาโปรแกรมภาษาหนึ่ง ขณะนี้มีประมาณ 11 การใช้งานที่แตกต่างกันของทับทิมโปรแกรมภาษาที่มีมากรุ่นเกลียวที่แตกต่างกันและไม่ซ้ำกัน
(น่าเสียดายที่มีเพียง 11 การติดตั้ง 11 ตัวเท่านั้นที่พร้อมใช้งานจริง แต่ภายในสิ้นปีนี้ตัวเลขอาจสูงถึงสี่หรือห้า) ( อัปเดต : ตอนนี้เป็น 5: MRI, JRuby, YARV (ล่าม สำหรับ Ruby 1.9), Rubinius และ IronRuby)
การใช้งานครั้งแรกไม่มีชื่อจริง ๆ ซึ่งทำให้มันดูงุ่มง่ามในการอ้างถึงและน่ารำคาญและสับสน มันมักถูกเรียกว่า "Ruby" ซึ่งยิ่งน่ารำคาญและสับสนมากกว่าไม่มีชื่อเพราะมันจะนำไปสู่ความสับสนไม่รู้จบระหว่างคุณสมบัติของภาษาโปรแกรมภาษา Ruby และการใช้ Ruby เฉพาะ
บางครั้งมันก็เรียกว่า "MRI" (สำหรับ "การใช้ทับทิมของ Matz"), CRuby หรือ MatzRuby
MRI ดำเนินทับทิมด้ายเป็นด้ายสีเขียวภายในล่าม แต่น่าเสียดายที่มันไม่อนุญาตให้เธรดเหล่านั้นถูกจัดตารางในแบบคู่ขนานพวกเขาสามารถเรียกใช้ทีละเธรดเท่านั้น
อย่างไรก็ตามจำนวนเธรด C ใด ๆ (POSIX เธรด ฯลฯ ) สามารถทำงานแบบขนานกับเธรดทับทิมดังนั้นไลบรารี C ภายนอกหรือส่วนขยาย MRI C ที่สร้างเธรดของตนเองยังสามารถทำงานแบบขนานได้
การใช้งานที่สองคือYARV (ย่อมาจาก "Yet Another Ruby VM") YARV ใช้ Ruby Threads เป็น POSIX หรือเธรด Windows NTอย่างไรก็ตามมันใช้ Global Interpreter Lock (GIL) เพื่อให้แน่ใจว่ามีเพียงหนึ่ง Ruby Thread เท่านั้นที่สามารถกำหนดเวลาจริงได้ในเวลาใดก็ได้
เช่นเดียวกับ MRI C Threads สามารถรันขนานกับ Ruby Threads ได้
ในอนาคตก็เป็นไปได้ว่า GIL อาจได้รับการแบ่งออกเป็นล็อคเม็ดเล็กมากขึ้นจึงช่วยให้มากขึ้นและรหัสมากขึ้นในการทำงานจริงในแบบคู่ขนาน แต่ที่ห่างไกลก็จะไม่ได้วางแผนเลย
JRuby ใช้ Ruby Threads เป็น Native Threadsโดยที่ "Native Threads" ในกรณีของ JVM นั้นหมายถึง "JVM Threads" อย่างชัดเจน JRuby ไม่มีการล็อคเพิ่มเติม ดังนั้นไม่ว่าเธรดเหล่านั้นสามารถรันในแบบขนานจริงหรือไม่ขึ้นอยู่กับ JVM: JVM บางอันใช้ JVM Threads เป็น OS Threads และบางเธรดเป็น Green Threads (JVM หลักจาก Sun / Oracle ใช้เธรด OS เฉพาะตั้งแต่ JDK 1.3)
XRubyยังดำเนินรูบีหัวข้อเป็น JVM กระทู้ อัปเดต : XRuby ตายแล้ว
IronRuby ใช้ Ruby Threads เป็น Native Threadsโดยที่ "Native Threads" ในกรณีของ CLR อย่างชัดเจนหมายถึง "CLR Threads" IronRuby กำหนดให้ไม่มีการล็อคเพิ่มเติมดังนั้นจึงควรรันแบบขนานตราบใดที่ CLR ของคุณรองรับ
Ruby.NETยังดำเนินรูบีหัวข้อเป็น CLR กระทู้ อัพเดต: Ruby.NET ตายแล้ว
Rubinius ดำเนินทับทิมด้ายสีเขียวกระทู้ภายในของเครื่องเสมือน อีกอย่างแม่นยำที่: Rubinius VM ส่งออกที่มีน้ำหนักเบามากมีความยืดหยุ่นมากเห็นพ้อง / ขนาน / นอกท้องถิ่นสร้างการควบคุมการไหลที่เรียกว่า " งาน " และทุกโครงสร้างอื่น ๆ พร้อมกัน (หัวข้อในการสนทนานี้ แต่ยังต , นักแสดงและสิ่งอื่น ๆ ) มีการใช้งานในทับทิมบริสุทธิ์โดยใช้งาน
(ปัจจุบัน) Rubinius ไม่สามารถกำหนดเวลาเธรดในแบบขนานได้อย่างไรก็ตามการเพิ่มที่ไม่ได้มีปัญหามากเกินไป: Rubinius สามารถรันอินสแตนซ์ VM หลายอินสแตนซ์ใน POSIX Threads หลายขนานพร้อมกันภายในกระบวนการ Rubinius เดียว เนื่องจากเธรดถูกนำไปใช้จริงใน Ruby พวกเขาสามารถเหมือนกับวัตถุ Ruby อื่น ๆ ที่ถูกทำให้เป็นอนุกรมและส่งไปยัง VM ที่แตกต่างกันใน POSIX Thread ที่แตกต่างกัน (นั่นเป็นรูปแบบเดียวกันกับที่ BEAM Erlang VM ใช้สำหรับการทำงานพร้อมกันของ SMP ซึ่งได้นำไปใช้กับ Rubinius Actorsแล้ว)
อัปเดต : ข้อมูลเกี่ยวกับ Rubinius ในคำตอบนี้เป็นเรื่องเกี่ยวกับ Shotgun VM ซึ่งไม่มีอยู่อีกต่อไป "ใหม่" C ++ VM ไม่ได้ใช้เธรดสีเขียวที่กำหนดไว้ในหลาย VM (เช่นรูปแบบ Erlang / BEAM) มันใช้ VM เดี่ยวแบบดั้งเดิมที่มีรูปแบบเธรด OS แบบดั้งเดิมหลายตัวเช่นเดียวกับที่ใช้โดย CLR, Mono และเกือบทุก JVM
MacRubyเริ่มต้นจากการเป็นพอร์ตของ YARV ด้านบนของ Objective-C Runtime และ CoreFoundation และ Cocoa Frameworks ก็มีตอนนี้แยกออกมาอย่างมีนัยสำคัญจาก YARV แต่ AFAIK มันขณะนี้ยังคงถือหุ้นเดียวกัน Threading รุ่นกับ YARV อัปเดต: MacRuby ขึ้นอยู่กับตัวรวบรวมขยะของแอปเปิ้ลซึ่งประกาศเลิกใช้แล้วและจะถูกลบออกใน MacOSX รุ่นที่ใหม่กว่า MacRuby นั้นไม่ตาย
พระคาร์ดินัลเป็นการนำทับทิมสำหรับเครื่องเสมือนนกแก้ว มันไม่ได้ดำเนินการตามหัวข้อเลย แต่เมื่อมันไม่ก็อาจจะใช้พวกเขาเป็นนกแก้วกระทู้ อัปเดต : ดูเหมือนว่าคาร์ดินัลจะไม่ทำงาน / ตายมาก
MagLevเป็นการนำทับทิมสำหรับอัญมณี / S สมอลล์ทอล์ค VM ฉันไม่มีข้อมูลว่าเกลียวรุ่น GemStone / S ใช้อะไรแบบจำลองเธรดที่ MagLev ใช้หรือแม้ว่าเธรดยังถูกใช้งาน (อาจไม่ใช่)
HotRubyคือไม่ได้ดำเนินการเต็มรูปแบบของทับทิมของตัวเอง มันเป็นการใช้งานของ YARV bytecode VM ใน JavaScript HotRuby ไม่รองรับเธรด (และ?) และเมื่อเป็นเช่นนั้นจะไม่สามารถทำงานแบบขนานได้เนื่องจาก JavaScript ไม่สนับสนุนการขนานแบบจริง มี HotRuby รุ่น ActionScript และจริง ๆ แล้ว ActionScript อาจรองรับขนานได้ อัปเดต : HotRuby ตายแล้ว
น่าเสียดายที่การใช้งานทับทิมเพียงสองใน 11 รายการนี้พร้อมใช้งานจริง: MRI และ JRuby
ดังนั้นหากคุณต้องการเธรดขนานจริง JRuby เป็นทางเลือกเดียวของคุณในปัจจุบัน - ไม่ใช่ว่ามันแย่มาก: JRuby เร็วกว่า MRI และมีเสถียรภาพมากกว่า
มิฉะนั้นโซลูชันทับทิม "คลาสสิค" คือการใช้กระบวนการแทนเธรดสำหรับการขนาน Ruby Core Library มีProcess
โมดูลที่มีProcess.fork
วิธีการซึ่งทำให้ง่ายต่อการแยกกระบวนการ Ruby อื่นออก นอกจากนี้ Ruby Standard Library ยังมีไลบรารี
Distributed Ruby (dRuby / dRb)ซึ่งอนุญาตให้โค้ด Ruby ถูกแจกจ่ายอย่างไม่น่าเชื่อในหลาย ๆ กระบวนการไม่เพียง แต่ในเครื่องเดียวกัน แต่ยังข้ามเครือข่าย
Ruby 1.8 เท่านั้นที่มีเธรดสีเขียวไม่มีวิธีสร้างเธรด "OS-level" จริง แต่ทับทิม 1.9 จะมีคุณสมบัติใหม่ที่เรียกว่าเส้นใยซึ่งจะช่วยให้คุณสร้างเธรดระดับ OS จริง น่าเสียดายที่ Ruby 1.9 ยังอยู่ในช่วงเบต้าซึ่งมีกำหนดจะคงตัวในอีกไม่กี่เดือนข้างหน้า
อีกทางเลือกหนึ่งคือการใช้ JRuby JRuby ใช้เธรดเป็นเธรดระดับ OS, ไม่มี "เธรดสีเขียว" อยู่ในนั้น JRuby เวอร์ชันล่าสุดคือ 1.1.4 และเทียบเท่ากับ Ruby 1.8
มันขึ้นอยู่กับการใช้งาน:
ทับทิมมีการปิดเป็นBlocks
, และlambdas
Procs
เพื่อใช้ประโยชน์อย่างเต็มที่จากการปิดและหลายคอร์ใน JRuby ผู้บริหารของ Javaมีประโยชน์ สำหรับ MacRuby ฉันเหมือนคิว
GCD ของ
โปรดทราบว่าการสามารถสร้างเธรด "OS-level" จริงไม่ได้หมายความว่าคุณสามารถใช้หลายแกนประมวลผลแบบขนานสำหรับการประมวลผลแบบขนาน ดูตัวอย่างด้านล่าง
นี่คือผลลัพธ์ของโปรแกรม Ruby แบบง่ายซึ่งใช้ 3 เธรดโดยใช้ Ruby 2.1.0:
(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
อย่างที่คุณเห็นในที่นี้มีเธรด OS สี่เธรด แต่มีเธรดเดียวเท่านั้นที่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-level" จริง ) และไม่มี 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
อีกครั้งโปรแกรมเดียวกัน แต่ตอนนี้กับ MRI เก่าที่ดี เนื่องจากความจริงที่ว่าการใช้งานนี้ใช้กรีนเธรดมีเธรดเดียวเท่านั้นที่ปรากฏขึ้น
(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
หากคุณสนใจ Ruby multi-threading คุณอาจพบว่ารายงานของฉันการดีบักโปรแกรมแบบขนานโดยใช้ fork fork ที่น่าสนใจ
สำหรับภาพรวมทั่วไปของทับทิมภายในทับทิมภายใต้กล้องจุลทรรศน์อ่านที่ดี
นอกจากนี้Ruby Threads และ Global Interpreter Lock ใน Cใน Omniref อธิบายในซอร์สโค้ดเหตุที่เธรด Ruby ไม่ทำงานแบบขนาน
วิธีการเกี่ยวกับการใช้drb ? มันไม่ได้เป็นมัลติเธรดที่แท้จริง แต่เป็นการสื่อสารระหว่างกระบวนการต่าง ๆ แต่คุณสามารถใช้ตอนนี้ได้ใน 1.8 และมันมีแรงเสียดทานค่อนข้างต่ำ
ฉันจะให้ "การตรวจสอบระบบ" ตอบคำถามนี้ ฉันกำลังรันรหัสเดียวกัน (ด้านล่างซึ่งคำนวณจำนวนเฉพาะ) ด้วย 8 Ruby threads ที่ทำงานบนเครื่อง i7 (4 hyperthreaded-core) ในทั้งสองกรณี ... การทำงานครั้งแรกคือ:
jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2014-02-03 6586) (เซิร์ฟเวอร์ OpenJDK 64- บิต VM 1.7.0_75) [amd64-java]
ประการที่สองคือ:
ruby 2.1.2p95 (2014-05-08) [x86_64-linux-gnu]
ที่น่าสนใจคือ CPU นั้นสูงกว่าสำหรับเธรด JRuby แต่เวลาในการดำเนินการจะสั้นกว่าเล็กน้อยสำหรับ Ruby ที่ตีความแล้ว เป็นการยากที่จะบอกจากกราฟ แต่การรันครั้งที่สอง (ตีความรูบี้) ใช้ซีพียูประมาณ 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
หากคุณใช้ MRI คุณสามารถเขียนโค้ดเธรดใน C เป็นส่วนขยายหรือใช้พลอย ruby-inline
หากคุณต้องการความเท่าเทียมในทับทิมสำหรับระบบระดับการผลิต (ซึ่งคุณไม่สามารถจ้างเบต้า) กระบวนการอาจเป็นทางเลือกที่ดีกว่า
แต่มันเป็นสิ่งที่ควรค่าแก่การลองใช้กับ JRuby ก่อน
นอกจากนี้หากคุณสนใจในอนาคตของเธรดภายใต้ Ruby คุณอาจพบว่าบทความนี้มีประโยชน์
Parallel.map(['a','b','c'], :in_processes=>3){...
นี่คือข้อมูลบางส่วนเกี่ยวกับ Rinda ซึ่งเป็นการใช้ทับทิมของ Linda (การประมวลผลแบบขนานและกระบวนทัศน์การคำนวณแบบกระจาย) http://charmalloc.blogspot.com/2009/12/linda-tuples-rinda-drb-parallel.html
เนื่องจากไม่สามารถแก้ไขคำตอบนั้นดังนั้นเพิ่มคำตอบใหม่ที่นี่
Update (2017/05/08)
บทความนี้เก่ามากและข้อมูลไม่ได้ติดตามดอกยาง (2017) ปัจจุบันต่อไปนี้เป็นอาหารเสริมบางส่วน:
โอปอลเป็นคอมไพเลอร์ซอร์สโค้ดของ Ruby to JavaScript นอกจากนี้ยังมีการนำ Corelib ของ Ruby มาใช้เป็นเครื่องมือพัฒนาที่ใช้งานอยู่ในปัจจุบันและมีเฟรมเวิร์ก (frontend) ที่ใช้งานได้ดี และการผลิตพร้อม เนื่องจากฐานบนจาวาสคริปต์มันไม่รองรับเธรดแบบขนาน
trufflerubyเป็นการใช้งานที่มีประสิทธิภาพสูงของภาษาการเขียนโปรแกรม Ruby สร้างขึ้นบน GraalVM โดย Oracle Labs TruffleRuby เป็นทางแยกของ JRuby รวมกับรหัสจากโครงการ Rubinius และยังมีรหัสจากการใช้มาตรฐานของ Ruby, MRI ยังคงพัฒนาอยู่ไม่พร้อมผลิต ทับทิมรุ่นนี้ดูเหมือนว่าเกิดมาเพื่อการแสดงฉันไม่รู้ว่ารองรับเธรดแบบขนานหรือไม่ แต่ฉันคิดว่ามันควรจะเป็น