Pregunta

Yo sé acerca de la "cooperativa" roscado de ruby utilizando hilos verdes.¿Cómo puedo crear un verdadero "sistema operativo" hilos en mi aplicación con el fin de hacer uso de múltiples núcleos de cpu para el procesamiento?

¿Fue útil?

Solución

Actualizado con Jörg Septiembre de 2011 comentario

Usted parece ser confuso dos muy cosas diferentes aquí:el Lenguaje de Programación Ruby y el específico modelo de subprocesamiento de uno implementación específica del Lenguaje de Programación Ruby.Allí actualmente son alrededor de 11 diferentes implementaciones de la Ruby Lenguaje de programación, con muy único y diferente de roscado modelos.

(Por desgracia, sólo dos de los 11 implementaciones son en realidad listo para su uso en producción, pero al final de el año en que el número de probablemente se irá hasta cuatro o cinco.) (Actualización:ahora es 5:La resonancia magnética, JRuby, YARV (el intérprete de Ruby 1.9), Rubinius y IronRuby).

  1. La primera implementación en realidad no tiene un nombre, que hace bastante torpe para referirse a ella y es realmente molesto y confuso.Es más a menudo se conoce como "Ruby", que es incluso más molesto y confuso que no tener nombre, porque conduce a la interminable confusión entre las características de Ruby Lenguaje de programación y un particular Implementación de Ruby.

    A veces se le llama "resonancia magnética" (por "Matz Rubí La aplicación"), CRuby o MatzRuby.

    La resonancia magnética implementa Ruby Hilos Hilos Verdes dentro de su intérprete.Por desgracia, no permite esos hilos para ser programado en paralelo, se puede ejecutar un solo hilo en un tiempo.

    Sin embargo, cualquier número de C Threads (Hilos POSIX, etc.) puede ejecutar en paralelo a la de Ruby Hilo, por lo que los C Bibliotecas, o resonancia magnética Extensiones en C que crear hilos de su propia todavía puede ejecutar en en paralelo.

  2. La segunda aplicación es YARV (corto para "Todavía Otro Ruby VM"). YARV implementa Ruby Hilos POSIX o Windows NT Hilos, sin embargo , se utiliza un Global de Intérprete De bloqueo (GIL) para asegurar que sólo una de Ruby Hilo puede ser en realidad programado en un momento.

    Como la resonancia magnética, los Hilos C puede en realidad paralela Ruby Hilos.

    En el futuro, es posible, que el GIL podría se rompen en más de grano fino de cerraduras, permitiendo que más y más código a ejecutar en paralelo, pero que tan lejos, es ni siquiera planeado sin embargo.

  3. JRuby implementa Ruby Subprocesos Subprocesos Nativos, donde "Threads Nativos" en el caso de la JVM, obviamente, significa "JVM Los hilos".JRuby impone ningún bloqueo adicional sobre ellos.Así, si los hilos realmente puede ejecutar en paralelo depende de la JVM:algunos Jvm implementar JVM Hilos como OS Hilos y algunos como Hilos Verdes.(De la corriente principal Jvm de Sun/Oracle utilizar exclusivamente OS hilos desde el JDK 1.3)

  4. XRuby también implementa Ruby Hilos como JVM Hilos. Actualización:XRuby está muerto.

  5. IronRuby implementa Ruby Subprocesos Subprocesos Nativos, donde "Threads Nativos" en caso de que el CLR, obviamente, significa "CLR Hilos".IronRuby impone ningún bloqueo adicional sobre ellos, así, se debe ejecutar en paralelo, siempre y cuando el CLR admite que.

  6. Ruby.NET también implementa Ruby Hilos como CLR Hilos. Actualización: Ruby.NET está muerto.

  7. Rubinius implementa Ruby Hilos Hilos Verdes dentro de su Máquina Virtual.Más precisamente:Rubinius VM exportaciones, muy ligero, muy flexible la simultaneidad/paralelismo/no local de control de flujo de construcción, llamado un "Tarea"y todos los demás de la concurrencia de las construcciones (Hilos en esta discusión, pero también Las continuaciones, Los actores y otras cosas) son puro Ruby, el uso de las Tareas.

    Rubinius no puede (en la actualidad) programación de Subprocesos en paralelo, sin embargo, la adición de que no es demasiado de un problema:Rubinius puede ya ejecutar varias VM instancias en varios Hilos POSIX en en paralelo, dentro de un proceso de Rubinius.Dado que los Hilos son de en realidad se implementa en Ruby, se puede, como cualquier otro Ruby objeto, se pueden serializar y enviada a otra VM en un diferente Los hilos POSIX.(Que es el mismo modelo de la VIGA Erlang VM usos de simultaneidad SMP.Ya está implementado para Rubinius Actores.)

    Actualización:La información acerca de Rubinius en esta respuesta es acerca de la Escopeta de la máquina virtual, que no existe más.El "nuevo" C++ VM no utiliza hilos verdes programadas a lo largo de múltiples máquinas virtuales (es decir,Erlang/HAZ de estilo), utiliza una más tradicional sola máquina virtual con múltiples nativo de OS hilos modelo, al igual que el empleado por, digamos, el CLR, Mono, y prácticamente todos los de la JVM.

  8. MacRuby comenzó como un puerto de YARV en la parte superior de la Objective-C en tiempo de ejecución y CoreFoundation y Cacao Marcos.Es ahora significativamente diferente de YARV, pero AFAIK actualmente todavía comparte el mismo Modelo de Subprocesamiento con YARV. Actualización: MacRuby depende de las manzanas recolector de basura que se declara obsoleto y será eliminado en las versiones posteriores de MacOSX, MacRuby es no-muertos.

  9. El cardenal es una Implementación de Ruby para el Parrot La Máquina Virtual.No aplicar hilos, sin embargo, cuando lo hace, es probable que se implementan como Parrot Hilos. Actualización:El cardenal parece muy inactivos o muertos.

  10. MagLev es una Implementación de Ruby para el Piedra Preciosa/S Smalltalk VM.No tengo información de lo que el modelo de subprocesamiento Piedra preciosa/S utiliza, qué modelo de subprocesamiento MagLev utiliza o incluso si los hilos son aún implementada (probablemente no).

  11. HotRuby es no una completa Implementación de Ruby de su propio.Se trata de una implementación de un YARV bytecode VM en JavaScript.HotRuby no admite hilos (¿todavía?) y cuando no, no van a ser capaces de ejecutar en paralelo, debido a que JavaScript no tiene soporte para cierto paralelismo.Hay una ActionScript la versión de HotRuby, sin embargo, y ActionScript en realidad podría apoyo paralelismo. Actualización:HotRuby está muerto.

Por desgracia, sólo dos de estos 11 Ruby Implementaciones son realmente listo para la producción:La resonancia magnética y JRuby.

Por lo tanto, si desea la verdadera hilos en paralelo, JRuby es actualmente su la única opción – no que eso es una mala:JRuby es más rápido que la RMN, y sin duda más estable.

De lo contrario, el "clásico" Ruby solución es el uso de procesos en lugar de hilos de paralelismo.Los Fundamentales De Ruby contiene la Process módulo con el Process.fork método que hace que sea muy fácil para el tenedor a otro Ruby proceso.También, el Rubí de la Biblioteca Estándar contiene el Distribuido Ruby (dRuby / dRb) la biblioteca, que permite Ruby código para ser trivialmente distribuido a través de múltiples procesos, no sólo en la misma máquina, sino también a través de la red.

Otros consejos

Ruby 1.8 sólo ha hilos verdes, no hay manera de crear un verdadero "sistema operativo" del hilo.Pero, ruby 1.9 tendrá una nueva característica llamada fibras, que le permitirá crear SO real a nivel de subprocesos.Por desgracia, Ruby 1.9 aún está en beta, está programado para ser estable en un par de meses.

Otra alternativa es el uso de JRuby.JRuby implementa hilos a nivel de SO theads, no hay "hilos verdes" en ella.La última versión de JRuby es 1.1.4 y es equivalente a Ruby 1.8

Depende de la implementación:

  • La resonancia magnética no tiene, YARV está más cerca.
  • JRuby y MacRuby tener.




Ruby tiene cierres como Blocks, lambdas y Procs.Para tomar la ventaja completa de cierres y de múltiples núcleos en JRuby, Java de los albaceas muy útil;para MacRuby me gusta GCD en las colas.

Tenga en cuenta que, de ser capaz de crear real "OS de" nivel de subprocesos no implica que se pueden utilizar varios núcleos de cpu para el procesamiento en paralelo.Mira los siguientes ejemplos.

Este es el resultado de un simple Ruby programa que utiliza 3 hilos usando 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 

Como se puede ver aquí, hay cuatro OS hilos, sin embargo, sólo el uno con el estado R se está ejecutando.Esto es debido a una limitación en la forma en Ruby hilos de ejecución.



Mismo programa, ahora con JRuby.Se puede ver a tres hilos con el estado R, lo que significa que se están ejecutando en paralelo.

(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 


El mismo programa, ahora con MacRuby.También hay tres subprocesos que se ejecutan en paralelo.Esto es debido a que MacRuby hilos son los hilos POSIX (real "OS de" nivel de subprocesos) y hay no 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 


Una vez más, el mismo programa, pero ahora con el buen viejo de resonancia magnética.Debido al hecho de que esta aplicación utiliza verde-hilos, sólo un subproceso se muestra

(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



Si usted está interesado en Ruby multi-threading usted podría encontrar mi informe Depuración de programas en paralelo usando fork controladores interesante.
Para una visión más general de la Ruby interna de Ruby Bajo un Microscopio es una buena lectura.
También, Ruby Hilos y el Bloqueo Global de Intérprete en C en Omniref explica en el código fuente por qué Ruby hilos no se ejecutan en paralelo.

Cómo sobre el uso de drb?No es real, multi-threading, pero la comunicación entre varios procesos, pero se puede usar ahora en la 1.8 y es bastante baja fricción.

Voy a dejar el "Monitor del Sistema" responder a esta pregunta.Estoy ejecutando el mismo código (abajo, a la que calcula los números primos) con 8 Ruby subprocesos que se ejecutan en un i7 (4 hyperthreaded-core) de la máquina en ambos casos...la primera carrera es con:

jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2014-02-03 6586) (OpenJDK Servidor de 64 Bits VM 1.7.0_75) [amd64-java]

El segundo es con:

ruby 2.1.2p95 (2014-05-08) [x86_64-linux-gnu]

Curiosamente, la CPU es mayor para JRuby hilos, pero el tiempo de realización es ligeramente más corto para el interpretado Ruby.Es un poco difícil de determinar a partir de la gráfica, pero la segunda (interpretado Ruby) ejecutar utiliza alrededor de 1/2 de la Cpu (sin hyperthreading?)

enter image description here

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

Si usted está utilizando la resonancia magnética, entonces usted puede escribir la rosca código en C, ya sea como una extensión o mediante el rubí en línea de la gema.

Si usted realmente necesita paralelismo en Ruby para un nivel de Producción del sistema (donde no se puede emplear una beta) los procesos son, probablemente, una mejor alternativa.
Pero, es definitivamente vale la pena probar los hilos en JRuby primera.

También si usted está interesado en el futuro de roscado en virtud de Ruby, usted puede encontrar este artículo útil.

Aquí hay algo de información sobre Rinda, que es la implementación de Ruby de Linda (procesamiento paralelo y distribuido paradigma de computación) http://charmalloc.blogspot.com/2009/12/linda-tuples-rinda-drb-parallel.html

Porque no podía editar la respuesta, por lo que añadir una nueva respuesta aquí.

Actualización(2017-05-08)

Este artículo es muy antigua, y la información no es seguir la corriente (2017) de la banda de rodadura, lo Siguiente es algunos suplemento:

  1. Opal es un Rubí de JavaScript fuente a fuente del compilador.También tiene una implementación de Ruby corelib, corriente muy activo develompent, y existen una gran cantidad de (frontend) marco trabajado en ella.y listo para producción.Debido a que la base de javascript, que no admiten hilos en paralelo.

  2. truffleruby es un alto rendimiento de la implementación del lenguaje de programación Ruby.Construido en el GraalVM por Oracle Laboratorios,TruffleRuby es un fork de JRuby, en combinación con el código de Rubinius proyecto, y también contiene el código de la implementación estándar de Ruby, la resonancia magnética, que todavía viven de desarrollo, no de producción listo.Esta versión de ruby parece nacido para el rendimiento, no sé si el soporte de hilos paralelos, pero creo que debería.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top