Ruby编程语言和特定的线程模型之一
Ruby编程语言的特定实现。那里
目前大约有11种不同"/>

红宝石有真正的多线程吗?

Does ruby have real multithreading?

我知道使用绿色线程的"红宝石""合作"线程。 如何在应用程序中创建真正的" OS级"线程,以便利用多个cpu内核进行处理?


更新为J?rg 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在其内部将Ruby线程实现为绿色线程
    口译员。不幸的是,它不允许那些线程
    要并行调度,它们只能在一个线程上运行一个线程
    时间。

    好。

    但是,可以运行任何数量的C线程(POSIX线程等)。
    与Ruby Thread并行,因此外部C库或MRI
    创建自己的线程的C扩展仍可以在其中运行
    平行。

    好。

  • 第二种实现是YARV("还"的缩写
    另一个Ruby VM")。YARV将Ruby线程实现为POSIX或
    Windows NT线程,但是,它使用全局解释器
    锁定(GIL)以确保实际上只能有一个Ruby Thread
    计划在任何时间。

    好。

    像MRI一样,C线程实际上可以与Ruby线程并行运行。

    好。

    将来,GIL可能会损坏
    进入更细粒度的锁,从而允许越来越多
    代码实际上可以并行运行,但是距离很远,
    甚至还没有计划

    好。

  • JRuby将Ruby线程实现为本机线程,
    其中,对于JVM,"本地线程"显然意味着" JVM
    线程"。JRuby不会对其施加任何额外的锁定。因此,
    这些线程是否可以并行运行取决于
    JVM:一些JVM将JVM线程实现为OS线程,而另一些
    作为绿线。 (从JDK 1.3开始,Sun / Oracle的主流JVM仅使用OS线程)

    好。

  • XRuby还将Ruby Threads实现为JVM Threads。更新:XRuby已死。

    好。

  • IronRuby将Ruby线程实现为本地线程,
    如果是CLR,"本地线程"显然意味着
    " CLR线程"。 IronRuby没有对它们施加任何额外的锁定,
    因此,只要您的CLR支持,它们就应该并行运行
    那。

    好。

  • Ruby.NET也将Ruby线程实现为CLR
    线程。更新:Ruby.NET已死。

    好。

  • Rubinius将Ruby线程实现为绿色线程
    在其虚拟机中。更准确地说:Rubinius
    VM导出非常轻巧,非常灵活
    并发/并行/非本地控制流构造,称为
    一个"任务",以及所有其他并发构造(
    这个讨论,还有Continuations,Actors和
    其他东西)是使用Tasks在纯Ruby中实现的。

    好。

    Rubinius无法(当前)并行调度线程,
    但是,添加这个问题并不是太大:Rubinius可以
    已经在多个POSIX线程中运行了多个VM实例
    在一个Rubinius过程中并行进行。由于线程是
    实际上是在Ruby中实现的,它们可以像其他任何Ruby一样
    对象,进行序列化并发送到不同虚拟机中的其他虚拟机
    POSIX线程。 (与BEAM Erlang VM的模型相同
    用于SMP并发。已经针对
    Rubinius演员。)

    好。

    更新:此答案中有关Rubinius的信息是关于Shotgun VM的,它不再存在。"新" C ++ VM不使用跨多个VM调度的绿色线程(即Erlang / BEAM样式),它使用具有多个本机OS线程模型的更传统的单个VM,就像CLR,Mono所采用的那样,几乎每个JVM。

    好。

  • MacRuby最初是YARV的端口,
    Objective-C运行时以及CoreFoundation和Cocoa框架。它
    现在与YARV有很大的不同,但AFAIK目前
    仍然与YARV共享相同的线程模型。
    更新:MacRuby依赖于已宣布弃用的苹果垃圾收集器,并将在更高版本的MacOSX中将其删除,因此MacRuby是不死的。

    好。

  • Cardinal是鹦鹉的Ruby实现
    虚拟机。它还没有实现线程,但是,
    当它这样做时,可能会将它们实现为Parrot
    线程。更新:红衣主教似乎非常不活跃/死了。

    好。

  • MagLev是GemStone / S的Ruby实现
    Smalltalk VM。我不知道什么线程模型
    GemStone / S使用MagLev使用什么线程模型,甚至
    线程甚至尚未实现(可能没有实现)。

    好。

  • HotRuby不是其完整的Ruby实现
    拥有。它是YARV字节码VM的实现
    JavaScript。 HotRuby不支持线程(还吗?)以及何时支持。
    这样做,它们将无法并行运行,因为JavaScript
    不支持真正的并行性。有一个动作脚本
    版本,但是ActionScript实际上可能
    支持并行性。更新:HotRuby已死。

    好。

  • 不幸的是,这11个Ruby实现中只有两个是
    实际上已经可以投入生产:MRI和JRuby。

    好。

    因此,如果您想要真正的并行线程,那么JRuby当前是您的
    唯一的选择–不是那不是一个坏选择:JRuby实际上更快
    比MRI更可靠。

    好。

    否则,"经典" Ruby解决方案是使用进程
    而不是并行线程。 Ruby核心库
    包含Process模块和Process.fork
    方法,使得分叉另一个Ruby很容易
    处理。 此外,Ruby标准库还包含
    分布式Ruby(dRuby / dRb)库,该库允许使用Ruby
    将代码分散在多个进程中,而不是
    只能在同一台计算机上,也可以跨网络。

    好。

    好。


    Ruby 1.8仅具有绿色线程,无法创建真正的" OS级"线??程。但是,ruby 1.9将具有称为纤维的新功能,该功能将允许您创建实际的OS级线程。不幸的是,Ruby 1.9仍处于beta中,计划在几个月内保持稳定。

    另一种选择是使用JRuby。 JRuby将线程作为操作系统级别的主题实现,其中没有"绿色线程"。 JRuby的最新版本是1.1.4,并且等效于Ruby 1.8


    这取决于实现:

    • MRI没有,YARV更近了。
    • JRuby和MacRuby都有。

    Ruby的闭包为BlockslambdasProcs。为了充分利用JRuby中的闭包和多个内核,Java的执行器派上了用场。对于MacRuby,我喜欢GCD的队列。

    请注意,能够创建真正的" OS级"线??程并不意味着您可以使用多个cpu内核进行并行处理。看下面的例子。

    这是一个简单的Ruby程序的输出,该程序在Ruby 2.1.0中使用3个线程:

    1
    2
    3
    4
    5
    6
    7
    (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的一个正在运行。这是由于Ruby线程的实现方式受到限制。

    相同的程序,现在与JRuby一起使用。您可以看到状态为R的三个线程,这意味着它们正在并行运行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    (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

    1
    2
    3
    4
    5
    6
    7
    (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。由于此实现使用绿色线程,因此仅显示一个线程

    1
    2
    3
    (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多线程感兴趣,您可能会发现我的报告"使用fork处理程序调试并行程序"很有趣。
    有关Ruby内部结构的更一般概述,请阅读显微镜下的Ruby。
    另外,Omniref中的C中的Ruby Threads和Global Interpreter Lock在源代码中解释了为什么Ruby线程不能并行运行。


    如何使用drb?它不是真正的多线程,而是多个进程之间的通信,但是您现在可以在1.8中使用它,并且摩擦很小。


    我将让"系统监视器"回答这个问题。在两种情况下,我都使用在i7(4个超线程核心)计算机上运行的8个Ruby线程执行相同的代码(下面将计算质数)...第一次运行是:

    jruby 1.5.6(ruby 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线程,CPU较高,但是对于解释后的Ruby,完成时间略短。从图中很难看出来,但是第二次(解释为Ruby)运行使用了大约1/2个CPU(没有超线程?)。

    enter image description here

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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-05-08)

    这篇文章很旧,并且信息不是最新的
    (2017年),下面是一些补充:

  • Opal是从Ruby到JavaScript的源到源编译器。它还有一个Ruby corelib的实现。它当前非常活跃,已经开发了,并且存在大量的(前端)框架。
    准备生产。由于基于javascript,因此不支持并行线程。

  • truffleruby是Ruby编程语言的高性能实现。 TruffleRuby是Oracle Labs在GraalVM上构建的,它是JRuby的分支,将其与Rubinius项目的代码结合在一起,还包含来自Ruby,MRI的标准实现的代码,仍在现场开发中,尚未投入生产。
    这个版本的ruby似乎是为性能而生的,我不知道是否支持并行线程,但我认为应该。


  • 这是有关Rinda的一些信息,它是Linda的Ruby实现(并行处理和分布式计算范例)http://charmalloc.blogspot.com/2009/12/linda-tuples-rinda-drb-parallel.html


    如果您确实需要在Ruby中为生产级系统(不能使用Beta)进行并行处理,则处理可能是一个更好的选择。
    但是,绝对值得首先在JRuby下尝试线程。

    另外,如果您对将来在Ruby下进行线程化感兴趣,则可能会发现本文很有用。


    如果您正在使用MRI,则可以将C中的线程代码作为扩展名或使用ruby-inline gem编写。


    推荐阅读

      在CentOS7上的内核中激活Intel VT-d

      在CentOS7上的内核中激活Intel VT-d,内核,文件,在许多教程之后,他们会要求你改变grup文件 /boot/grup/grup.conf ..但在Centos7中没有/bo

      4000元的32纳米内核i3加单配置

      4000元的32纳米内核i3加单配置,,今天,我将介绍一套相似的配置,给你的,但这种配置不是网吧用户,但是大量的消费者,配置上也采用530大核心i3处理

      未知软件异常应用程序错误解决方案

      未知软件异常应用程序错误解决方案,,我有很多朋友的电脑未知软件异常应用程序错误的问题,对于异常未知的软件异常中的应用一般提示(0xc00000

      设置线程名称|tomcat线程名称设置

      设置线程名称|tomcat线程名称设置,,1. tomcat线程名称设置一.tomcat的优化1.tomcat的自身调优采用动静分离调优Tomcat线程池调优Tomcat的

      小米手机安装的应用程序包在哪里

      小米手机安装的应用程序包在哪里,,问题: 下载小米手机系统的安装文件在哪里 答案uff1a 下载应用程序包位置:SD卡>下载。 (摘自:小米手册:米

      多线程cpu电脑|多线程的CPU

      多线程cpu电脑|多线程的CPU,,1. 多线程的CPU四核心四线程,表示这个电脑的CPU核心是4个核心、4个线程的。电脑CPU的核心数量和线程数量越多,

      应用程序对象

      应用程序对象,,应用程序对象是一个应用程序级对象,用于在所有用户之间共享信息,并且在Web应用程序运行期间可以保存数据。 应用的性质: 方法