Question

Je sais au sujet de la "coopérative" le filetage à l'aide de ruby fils verts.Comment puis-je créer une véritable "OS" au niveau de threads dans mon application afin de rendre l'utilisation de plusieurs cœurs de processeur pour le traitement?

Était-ce utile?

La solution

Mis à jour avec de Jörg Sept 2011 commentaire

Vous semblez être déroutant deux très différentes choses ici:l' Langage de Programmation Ruby et le modèle de thread de l'un mise en œuvre spécifique du Langage de Programmation Ruby.Il y sont actuellement de l'ordre de 11 différentes implémentations du Ruby Langage de programmation, avec très d'unique et de différent threading modèles.

(Malheureusement, seulement deux de ces 11 implémentations sont en fait prêt pour une utilisation en production, mais par la fin de l'année, ce nombre sera probablement aller jusqu'à quatre ou cinq.) (Mise à jour:c'est maintenant à 5:L'IRM, JRuby, YARV (l'interpréteur Ruby 1.9), Rubinius et IronRuby).

  1. La première mise en œuvre n'est pas réellement un nom, qui le rend assez difficile à se référer à elle et c'est vraiment ennuyeux et source de confusion.Il est le plus souvent désigné comme "Ruby", ce qui est encore de plus ennuyeux et de confusion que de ne pas avoir de nom, parce qu'il conduit à d'interminables confusion entre les fonctions de l'Ruby Langage de programmation et un Rubis particulière de mise en Œuvre.

    Elle est aussi parfois appelée "IRM" (pour "Matz Ruby La mise en œuvre"), CRuby ou MatzRuby.

    L'IRM met en œuvre Ruby Fils en tant que Fils Verts à l'intérieur de son interprète.Malheureusement, il ne permet pas à ceux des threads pour être programmée en parallèle, ils ne peuvent exécuter un thread à un temps.

    Cependant, un certain nombre de Fils C (POSIX Threads, etc.) pouvez l'exécuter en parallèle à la Ruby Thread, donc C externe Bibliothèques, ou IRM C Extensions de créer des threads de leur propre peut toujours s'exécuter en en parallèle.

  2. La deuxième application est YARV (abréviation de "Encore Un autre Rubis VM"). YARV implémente Ruby Threads comme POSIX ou Windows NT Fils, cependant, il utilise un Mondial Interprète De verrouillage (GIL) pour s'assurer qu'un seul Ruby Thread peut effectivement être prévu à la fois.

    Comme l'IRM, les Threads C peut en fait parallèles à Ruby Threads.

    Dans l'avenir, il est possible, que le GIL peut obtenir cassé plus fine des serrures, permettant ainsi à plus de et plus code pour exécuter en parallèle, mais qui est si loin, il est même pas prévu encore.

  3. JRuby met en œuvre Ruby Threads que les Threads Natifs, où les "Threads Natifs" dans le cas de la JVM, c'est évidemment "de la JVM Fils".JRuby impose pas de verrouillage complémentaire sur eux.Donc, si ces threads peut s'exécuter en parallèle dépend la JVM:certaines machines virtuelles en œuvre de la JVM des Threads comme OS de Threads et de certains en tant que Fils Verts.(Le courant de la Jvm de Sun/Oracle-utiliser exclusivement des OS threads depuis le JDK 1.3)

  4. XRuby aussi met en œuvre Ruby Fils en tant que Fils de la JVM. Mise à jour:XRuby est mort.

  5. IronRuby met en œuvre Ruby Threads que les Threads Natifs, où les "Threads Natifs" dans le cas de la CLR signifie évidemment "CLR Fils".IronRuby impose pas de verrouillage supplémentaire sur eux, alors, ils doivent s'exécuter en parallèle, aussi longtemps que votre CLR prend en charge qu'.

  6. Ruby.NET aussi met en œuvre Ruby Threads comme CLR Fils. Mise à jour: Ruby.NET est mort.

  7. Rubinius met en œuvre Ruby Fils en tant que Fils Verts à l'intérieur de sa Machine Virtuelle.Plus précisément:le Rubinius VM exportations d'un très léger, très souple la simultanéité/parallélisme/non-local de contrôle des flux de construire, appelé un "Tâche"et tous les autres de la simultanéité des constructions (les Threads cette discussion, mais aussi Les Continuations, Les acteurs et d'autres choses) sont mis en œuvre dans le plus pur Rubis, à l'aide de Tâches.

    Rubinius ne peut pas (encore) de l'annexe de Threads en parallèle, cependant, l'ajout qui n'est pas trop un problème:Rubinius peut déjà exécuter plusieurs instances d'ordinateurs virtuels dans plusieurs Threads POSIX dans en parallèle, dans un délai d'un Rubinius processus.Etant donné que les Threads sont effectivement mises en Ruby, ils peuvent, comme tous les autres Ruby objet, être sérialisé et envoyée à une autre machine virtuelle dans un autre POSIX Thread.(C'est le même modèle de la POUTRE Erlang VM utilise pour SMP simultanéité.Il est déjà mis en œuvre pour Rubinius Acteurs.)

    Mise à jour:Les informations à propos de Rubinius dans cette réponse, c'est sur le Fusil à pompe VM, qui n'existe plus.La "nouvelle" C++ VM ne pas utiliser de fils verts prévue à travers plusieurs machines virtuelles (c'est à direErlang/FAISCEAU de style), il utilise une approche plus traditionnelle de machine virtuelle avec plusieurs système d'exploitation natif des threads modèle, tout comme celui utilisé par, disons, le CLR, Mono, et à peu près tous de la JVM.

  8. MacRuby qui a commencé comme un port de YARV sur le dessus de la Objective-C Runtime et CoreFoundation de Cacao et de Cadres.Il a maintenant considérablement divergé à partir de YARV, mais autant que je sache il actuellement encore actions le même Modèle de thread avec YARV. Mise à jour: MacRuby dépend de pommes garbage collector qui est déclarée obsolète et sera supprimée dans les versions ultérieures de MacOSX, MacRuby est morts-vivants.

  9. Le Cardinal est un Rubis de mise en Œuvre de la Parrot La Machine Virtuelle.Il n'a pas d'implémenter les threads encore, cependant, quand il le fait, il va probablement mettre en œuvre, Parrot Fils. Mise à jour:Le Cardinal semble très inactif/morts.

  10. MagLev est un Rubis de mise en Œuvre de la Pierres Précieuses/S Smalltalk VM.Je n'ai pas d'informations à ce modèle de thread Pierres précieuses/S utilise, ce modèle de thread MagLev utilise ou même si les fils sont même encore mis en œuvre (probablement pas).

  11. HotRuby est pas plein de Rubis de la mise en Œuvre de ses propre.C'est une mise en œuvre d'un YARV bytecode de la VM en Le JavaScript.HotRuby ne prend pas en charge les threads (encore?) et quand il n', ils ne seront pas en mesure d'exécuter en parallèle, parce que JavaScript n'a pas de support pour de vrai parallélisme.Il y a un code ActionScript la version de HotRuby, cependant, et ActionScript pourrait en fait support de parallélisme. Mise à jour:HotRuby est mort.

Malheureusement, seulement deux de ces 11 Ruby Implémentations sont en fait prêt à la production de:L'IRM et JRuby.

Donc, si vous voulez un vrai fils parallèles, JRuby est actuellement votre seul choix – pas que c'est une mauvaise:JRuby est effectivement plus rapide que l'IRM, et sans doute plus stable.

Sinon, le "classique" Ruby solution est d'utiliser les processus de au lieu de threads pour le parallélisme.La Librairie Principale contient le Process module avec l' Process.fork méthode qui en fait mort facile à fourche d'un autre Rubis processus.Aussi, le Rubis de la Bibliothèque Standard contient les Distribué Ruby (dRuby / dRb) la bibliothèque, qui permet de Ruby code pour être trivialement distribué entre plusieurs processus, de ne pas que sur la même machine, mais aussi à travers le réseau.

Autres conseils

Ruby 1.8 a seulement des fils verts, il n'y a aucun moyen de créer un vrai "OS", au niveau du filetage.Mais, ruby 1.9 aura une nouvelle fonctionnalité appelée fibres, ce qui vous permettra de créer des OS au niveau des threads.Malheureusement, Ruby 1.9 est encore en version bêta, elle est prévue pour être stable dans une couple de mois.

Une autre alternative est d'utiliser JRuby.JRuby met en œuvre des threads comme niveau de l'OS theads, il n'existe pas de "fils verts" en elle.La dernière version de JRuby est 1.1.4 et est équivalent à Ruby 1.8

Il dépend de la mise en œuvre:

  • L'IRM n'a pas, YARV est plus proche.
  • JRuby et MacRuby ont.




Ruby a fermetures comme Blocks, lambdas et Procs.Pour profiter pleinement de fermetures et de plusieurs cœurs en JRuby, Java est exécuteurs venir dans maniable;pour MacRuby j'aime PGCD de files d'attente.

Notez que, être en mesure de créer réel "OS" au niveau de threads ne signifie pas que vous pouvez utiliser plusieurs cœurs de processeur pour le traitement en parallèle.Regardez les exemples ci-dessous.

C'est la sortie de un simple Ruby programme qui l'utilise 3 fils à l'aide de 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 

Comme vous pouvez le voir ici, il y a quatre OS threads, mais seulement l'un avec l'état R est en cours d'exécution.Cela est dû à une limitation dans la façon dont les Rubis, les threads sont mis en œuvre.



Même programme, maintenant avec JRuby.Vous pouvez voir les trois fils avec l'état R, ce qui signifie qu'ils sont exécutés en parallèle.

(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 


Le même programme, maintenant avec MacRuby.Il y a également trois threads s'exécutant en parallèle.C'est parce que MacRuby threads POSIX threads (réel "OS" au niveau de threads et il en est pas de 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 


Encore une fois, le même programme, mais maintenant avec le bon vieux IRM.En raison du fait que cette application utilise le vert-fils, un seul thread affiche

(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 vous êtes intéressé par Ruby le multi-threading, vous pourriez trouver mon rapport Débogage de programmes parallèles l'aide d'une fourchette gestionnaires intéressant.
De plus pour un aperçu général de l'Ruby internes Ruby Sous un Microscope est une bonne lecture.
Aussi, Ruby Fils et le Global Interprète de Verrouillage en C dans Omniref explique dans le code source pourquoi Ruby fils ne tournent pas en parallèle.

Comment sur l'utilisation de drb?Ce n'est pas réel, multi-threading, mais la communication entre plusieurs processus, mais vous pouvez maintenant l'utiliser en 1.8 et il est assez faible friction.

Je vais laisser le "Moniteur Système" répondre à cette question.Je suis d'exécuter le même code (ci-dessous, qui calcule les nombres premiers) avec 8, Ruby threads en cours d'exécution sur un i7 (4 hyperthread-core) de la machine dans les deux cas...la première manche est avec:

jruby 1.5.6 (ruby 1.8.7 version 249) (2014-02-03 6586) (OpenJDK 64-Bit Server VM 1.7.0_75) [amd64-java]

La deuxième est avec:

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

Fait intéressant, le PROCESSEUR est plus élevé pour les JRuby fils, mais le temps de la fin est légèrement plus courte pour le interprétée Ruby.C'est un peu difficile à dire à partir du graphique, mais la seconde (interprété Ruby) utilise environ 1/2 de la Cpu (pas d'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 vous êtes à l'aide de l'IRM, alors vous pouvez écrire la partie filetée du code en C soit comme une extension ou à l'aide de ruby-inline gem.

Si vous avez vraiment besoin de parallélisme dans le Rubis pour un niveau de Production system (où vous ne pouvez pas employer un bêta) les processus sont probablement une meilleure alternative.
Mais, il est certainement la peine d'essayer de threads sous JRuby premier.

Aussi, si vous êtes intéressé à l'avenir de filetage en vertu de Ruby, vous trouverez peut-être ce l'article utile.

Voici quelques informations sur Rinda qui est Ruby mise en œuvre de Linda (traitement parallèle et distribué paradigme informatique) http://charmalloc.blogspot.com/2009/12/linda-tuples-rinda-drb-parallel.html

Parce que ne pouvait pas modifier cette réponse, il faut donc ajouter une nouvelle réponse ici.

Mise à jour(2017-05-08)

Cet article est très ancienne, et l'information n'est pas suivre en cours (2017) de la bande de roulement, voici un complément:

  1. Opale est un Ruby, JavaScript source-à-source du compilateur.Il dispose également d'une mise en œuvre de la Ruby corelib, Ce courant très actif develompent, et il existe beaucoup d' (frontend) cadre travaillé sur elle.et prêt pour la production.Parce que sur la base de javascript, pas de support des threads parallèles.

  2. truffleruby est une haute performance de la mise en œuvre du langage de programmation Ruby.Construit sur le GraalVM par Oracle Labs,TruffleRuby est un fork de JRuby, en la combinant avec le code de la Rubinius projet, et contenant le code de l'implémentation standard de Ruby, IRM, vivent encore de développement, pas de prêt de production.Cette version rubis semblent comme né pour la performance, je ne sais pas si le support des threads parallèles, mais je pense qu'il devrait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top