我使用green threads瞭解紅寶石的「協作」線程。如何在我的應用程序中創建真正的「OS級」線程,以便利用多個cpu核心進行處理?紅寶石有真正的多線程嗎?
回答
與約爾格的2011年9月評論
更新你似乎是令人費解!非常不同,這裏的東西: Ruby編程語言和一個 具體實施Ruby編程語言的特定線程模型。目前有 大約有11種不同的Ruby 編程語言的實現,其中有很不同和唯一線程 模型。
(不幸的是,只有其中的兩個11所實現的實際上是 可供生產使用,但到今年年底,這個數字 將可能上升到四,五。)(更新:它現在是5: MRI,JRuby,YARV(Ruby 1.9的解釋器),Rubinius和IronRuby)。
首次實施實際上並沒有一個名字, 使得它比較尷尬提及它,實在是煩人和 混亂。它通常被稱爲「Ruby」,它甚至比沒有名字更令人討厭和困惑,因爲它會導致Ruby 編程語言和特定Ruby實現之間的無窮混淆。
它有時也被稱爲「MRI」(對於「Matz's Ruby 實現」),CRuby或MatzRuby。
MRI implements Ruby Threads as Green Threads within its interpreter。不幸的是,它不允許並行調度那些線程 ,它們只能在 時間運行一個線程。
然而,任何編號C線程(POSIX線程等)可以運行在平行於Ruby的線程 ,所以外部C庫,或MRI C擴展,創造屬於自己的線程並行 仍然可以運行。
第二個實現是YARV(「Yet Another Ruby VM」的縮寫)。然而,它使用全局解釋器 鎖定(GIL)來確保在任何時候只有一個Ruby線程實際上可以被排列爲 。
像MRI,C線程可以實際上平行於Ruby線程運行。
在未來,它是可能的是,GIL 可能獲得破 分解成更細粒度鎖,從而使越來越多的 代碼實際並行運行,但這是那麼遙遠,它是 甚至沒有計劃呢。
JRubyimplements Ruby Threads as Native Threads, 其中 「本地線程」 在JVM的情況下,顯然意味着 「JVM 線程」。 JRuby對它們沒有額外的鎖定。因此, 這些線程是否可以實際並行運行取決於JVM的 :某些JVM將JVM線程實現爲OS線程,並將一些 作爲綠色線程實現。 (Sun/Oracle的主流JVM使用自JDK 1.3以來的獨佔操作系統線程)
XRuby也implements Ruby Threads as JVM Threads。 更新:XRuby已經死了。
IronRubyimplements Ruby Threads as Native Threads, 其中 「本地線程」 在CLR的情況下顯然意味着 「CLR線程」。 IronRuby不會額外鎖定它們,因此,它們應該並行運行,只要您的CLR支持 即可。
Ruby.NET也implements Ruby Threads as CLR Threads。 更新: Ruby.NET已經死亡。
Rubiniusimplements Ruby Threads as Green Threads within its Virtual Machine。更準確地說是Rubinius的 VM出口非常輕,非常靈活 併發/並行/非本地控制流結構,稱爲 一個「Task」,和所有其他併發結構(版面中 這個討論,而且Continuations, Actors和 其他的東西)在純Ruby中使用任務來實現。
Rubinius的不能(目前)調度線程並行, 然而,並稱不是太大的問題:Rubinius的可 已經run several VM instances in several POSIX Threads in parallel,一個Rubinius的過程內。由於線程實際上是在Ruby中實現的 ,因此它們可以像任何其他Ruby 對象一樣,被序列化併發送到不同的POSIX Thread中的VM。 (這與BEAM Erlang VM 用於SMP併發的模型相同。它已經是implemented for Rubinius Actors。)
更新:關於Rubinius在這個答案的信息是關於Shotgun虛擬機,它不再存在。 「新」C++虛擬機不使用跨多個虛擬機調度的綠色線程(例如Erlang/BEAM風格),它使用更傳統的單一虛擬機和多種本地操作系統線程模型,就像CLR所使用的那樣,單聲道,幾乎每個JVM。
MacRuby作爲YARV的一個端口,在 Objective-C運行時和CoreFoundation和Cocoa框架之上開始。它現在 已經明顯偏離了YARV,但是AFAIK它目前 仍然是shares the same Threading Model with YARV。 更新: MacRuby依賴於蘋果垃圾收集器,它已被宣佈不推薦使用,並將在更高版本的MacOSX中刪除,MacRuby不死。
Cardinal是Parrot Virtual Machine的Ruby實現。它還沒有實現線程,但是,當它這樣做時,它可能會將它們實現爲Parrot Threads。 更新:紅衣主教看起來非常不活躍/死亡。
MagLev是GemStone/S Smalltalk VM的Ruby實現。我不知道GemStone/S使用的線程模型 ,MagLev使用什麼線程模型,甚至線程甚至還未實現(可能不是)。
HotRuby是不其 自己的完整的Ruby實現。它是一個在JavaScript中執行的YARV字節碼虛擬機。 HotRuby不支持線程(還有?),並且它在 做的時候,它們將不能並行運行,因爲JavaScript 不支持真正的並行。然而,HotRuby有一個ActionScript 版本,而ActionScript可能實際上支持並行性。 更新:HotRuby已死亡。
遺憾的是,只有其中兩個11所Ruby實現的是 實際生產就緒:MRI和JRuby。因此,如果你想要真正的並行線程,JRuby目前只是你的 唯一的選擇 - 這不是一個壞的選擇:JRuby實際上比MRI更快 ,並且可以說更穩定。
否則,「古典」Ruby解決方案是使用進程 而不是線程進行並行處理。紅寶石核心庫 包含Process
module與Process.fork
method,這使得它很容易分叉另一個紅寶石 過程。此外,Ruby標準庫包含 Distributed Ruby (dRuby/dRb)庫,該庫允許在多個進程間輕鬆地分佈代碼,而不僅僅在同一臺計算機上,而且在整個網絡上進行分佈式編程,而不僅僅是 。
Ruby 1.8只有綠色的線程,沒有辦法創建一個真正的「OS級」線程。但是,ruby 1.9將會有一個稱爲纖維的新功能,它可以讓你創建實際的OS級別的線程。不幸的是,Ruby 1.9仍處於測試階段,它計劃在幾個月內保持穩定。
另一種選擇是使用JRuby。 JRuby將線程實現爲OS級別的線程,其中沒有「綠色線程」。 JRuby的最新版本是1.1.4,相當於Ruby 1.8
如何使用drb?這不是真正的多線程,而是幾個進程之間的通信,但是現在可以在1.8版本中使用它,並且它的摩擦相當低。
如果您正在使用MRI,那麼您可以使用C語言編寫線程代碼作爲擴展名或使用ruby-inline gem。
如果您真的需要在Ruby中爲生產級別系統(不能使用測試版)進行並行化,那麼進程可能是更好的選擇。
但是,它絕對值得在JRuby下首先嚐試線程。
此外,如果您對Ruby下的線程未來感興趣,您可能會發現article有用。
JRuby是一個不錯的選擇。對於使用進程的並行處理,我喜歡https://github.com/grosser/parallel`Parallel.map(['a','b','c'],:in_processes => 3){...' – user454322 2014-02-03 16:10:09
這裏是關於Rinda一些信息是Ruby實現琳達的(並行處理和分佈式計算模式)http://charmalloc.blogspot.com/2009/12/linda-tuples-rinda-drb-parallel.html
這取決於實現:
- RMI沒有,YARV是接近。
- JRuby和MacRuby都有。
Ruby有closures如Blocks
,lambdas
和Procs
。爲了充分利用JRuby中的閉包和多核,Java's executors派上用場;對於MacRuby我喜歡GCD's queues。
請注意,能夠創建真正的「OS級」線程並不意味着您可以使用多個cpu核心進行並行處理。看下面的例子。
這是a simple Ruby program which uses 3 threads使用Ruby 2.1.0輸出:
([email protected] ~)$ 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
運行。這是由於Ruby的線程被實現的限制。
同一個節目,現在使用JRuby。您可以看到三個狀態爲R
的線程,這意味着它們並行運行。
([email protected] ~)$ 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 threads are POSIX threads(真正的「操作系統級」線程),並有no GVL
([email protected] ~)$ 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
再次,相同的程序,但現在用好老RMI。由於這個實現使用綠色線程的事實,只有一個線程顯示出來
([email protected] ~)$ 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中多線程,你可能會發現我的報告Debugging parallel programs using fork handlers有趣。
對於Ruby內部的更一般的概述Ruby Under a Microscope是一個很好的閱讀。
另外,Omniref中的Ruby Threads and the Global Interpreter Lock in C在源代碼中解釋了爲什麼Ruby線程不能並行運行。
我會讓「系統監視器」回答這個問題。我正在執行相同的代碼(下面計算素數),在這兩種情況下,運行在i7(4超線程核心)機器上的8個Ruby線程......第一次運行是:
jruby 1.5.6 (紅寶石1.8.7 PATCHLEVEL 249)(2014年2月3日6586) (OpenJDK的64位服務器VM 1.7.0_75)AMD64的Java]
第二個是與:
紅寶石2.1.2p95 (2014-05-08)[x86_64-linux-gnu]
有趣的是,JRuby線程的CPU更高,但解釋Ruby的完成時間略短。這是一種很難從圖說,但第二(解釋Ruby)的運行使用約1/2的CPU(無超線程?)
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
因爲無法編輯答案,所以在這裏添加一個新的答覆。
更新(2017年5月8日)
這篇文章很老了,信息不遵循當前 (2017)胎面,以下是一些補充:
Opal是Ruby to JavaScript源到源編譯器。它還具有Ruby corelib的實現,它是當前非常活躍的開發工具,並且存在大量的(前端)框架。 和生產準備。因爲基於JavaScript,它不支持並行線程。
truffleruby是Ruby編程語言的高性能實現。 TrufleRuby由Oracle Labs構建於GraalVM上,是JRuby的一個分支,將其與Rubinius項目的代碼結合起來,還包含Ruby,MRI的標準實現代碼,仍然是實時開發,而不是生產準備。 這個版本的ruby好像天生就是性能,我不知道是否支持並行線程,但我認爲它應該。
- 1. 多線程紅寶石
- 2. 紅寶石多線程/多讀數
- 3. Watir的紅寶石線程
- 4. 紅寶石線程塊?
- 5. 紅寶石重複線程
- 6. 紅寶石線程池
- 7. 紅寶石有退出嗎?
- 8. 紅寶石單線這可能嗎?
- 9. 紅寶石線程編程,紅寶石相應的Java等待/通知/ notifyAll的
- 10. MathJax寶石真的有用嗎?
- 11. 刪除「」從線紅寶石
- 12. 印刷線紅寶石
- 13. 評估%×()爲真或假的紅寶石
- 14. Twitter的紅寶石寶石
- 15. 紅寶石線程仍然阻塞
- 16. 紅寶石獨角獸 - 線程異常
- 17. 紅寶石睡眠在線程
- 18. 紅寶石多行正則表達式
- 19. 有沒有更好的紅寶石線程池的lib
- 20. 那裏有紅隼寶石嗎?
- 21. 紅寶石有日誌查看器嗎?
- 22. 紅寶石多線程的生產者 - 消費者
- 23. 紅寶石多個線程從相同的散列讀取
- 24. 是使用線程和紅寶石機械化安全嗎?
- 25. 這是紅寶石代碼線程安全嗎?
- 26. 紅寶石 - 一切都評估爲真
- 27. 紅寶石:獲取值,如果真或
- 28. 方法紅寶石返回真或假
- 29. 真棒打印紅寶石哈希
- 30. 紅寶石radio_button_tag不服從`檢查:真'
Ruby 1.8只有綠色線程是錯誤的,Ruby 1.8的幾個實現具有本機線程:JRuby,XRuby,Ruby.NET和IronRuby。 纖維不允許創建原生線程,它們比線程*更輕量。它們實際上是半協程,即它們是合作的。 – 2008-09-11 22:32:29
我認爲從Josh的回答可以很明顯地看出,當他說Ruby 1.8時,他的意思是Ruby 1.8是運行時,也就是MRI,而不是Ruby 1.8。 – Theo 2011-04-22 19:46:18