Énoncé (fichier pdf) - LabUnix
Transcription
Énoncé (fichier pdf) - LabUnix
Devoir #2 — INF5171 (gr. 20) Automne 2016 Date de remise: Mardi, 22 novembre, 13h30. Un travail remis après l’heure indiquée sera en retard ⇒ pénalité de 10 % par jour, partiel ou complet. Aucun travail ne sera accepté après Jeudi, 24 novembre, 16h00. Mise en oeuvre d’un espace de tuples de style «Linda» Les espaces de tuples La notion «d’espace de tuples» a été introduite par Carriero & Gelernter dans le cadre d’un langage appelé Linda.1 Linda est un «langage de coordination» qui peut s’intégrer à divers langages de programmation — des variantes existent pour C, Java, Ruby, ainsi que de nombreux autres langages. Linda combine des éléments de programmation parallèle par variables partagées et par échange de messages : un espace de tuples est partagé entre des processus — chacun avec son contexte privé — qui utilisent cet espace pour échanger de l’information, de façon concurrente et atomique. Dans ce qui suit, nous allons présenter une version Ruby des notions de tuples et d’espace de tuples à la Linda, version que vous devrez mettre en oeuvre. • Un tuple est une séquence finie d’éléments, de types variés, dont le premier élément est nécessairement un Symbol — élément qu’on appelle la clé du tuple. Un tuple est simplement un Array dont le premier élément est un Symbol — donc un Array tel que size >= 1. Voici quelques exemples : # Un tuple ( de taille 1) avec une clé : foo [: foo ] # Un tuple ( de taille 2) avec une clé : foo et un champ : bar [: foo , : bar ] # Un tuple ( de taille 3) avec une clé : bar et des champs " abc " et 10 [: bar , " abc " , 10] 1 N. Carriero and D. Gelernter. «Linda in context.» CACM, 32(4):444–458, April 1989. 1 INF5171 (gr. 20) Devoir #2 (Automne 2016) 2 • Un espace de tuples — classe TupleSpace — est une collection de tuples. Un tuple peut apparaître plusieurs fois ; un espace de tuples est donc un multi-ensemble2 de tuples. • Étant donné un TupleSpace ts, les trois méthodes de base associées à ts sont les suivantes : – ts.put le_tuple Ajoute dans ts le_tuple indiqué. – ts.take patron Retire de ts un (1) tuple qui matche le patron — voir plus bas pour la notion de patron de tuples — et retourne le tuple retiré. Si aucun tuple qui matche le patron n’est présent, la méthode bloque jusqu’à ce qu’un tuple approprié soit disponible. Si plusieurs tuples matchent le patron, un (et un seul) tuple est retiré et retourné, tuple choisi de façon arbitraire (au choix de l’implémentation). – ts.read patron Retourne un tuple de ts qui matche le patron indiqué, mais sans retirer le tuple. Cette méthode bloque et fait un choix arbitraire si plusieurs tuples matchent de la même façon que take. Ces trois méthodes sont toujours exécutées de façon atomique et indivisible, même en présence de threads multiples utilisant et manipulant l’espace de tuples. Soulignons que d’autres méthodes sont disponibles, que vous devrez aussi mettre en oeuvre, mais elles ne sont pas décrites dans le présent document : voir plutôt le fichier lib/tuplespace/tuplespace.rb, la documentation yard,3 ainsi que les fichiers de test. 2 3 En anglais, on dit aussi multiset ou bag. http://www.labunix.uqam.ca/~tremblay/INF5171/Devoirs/TupleSpaceDoc/ INF5171 (gr. 20) Devoir #2 (Automne 2016) 3 • Un patron de tuples, utilisé dans les méthodes take et read,4 permet de décrire un ensemble de tuples «potentiels». Les principaux patrons sont les suivants : – Patrons utilisés directement comme argument, donc au plus haut niveau, par exemple, «ts.take nil» ou «ts.take :foo» : Matche n’importe quel tuple Matche n’importe quel tuple (donc de taille arbitraire) dont la clé est :foo /pat/ Matche n’importe quel tuple (de taille arbitraire) dont la clé matche l’expression régulière /pat/ nil :foo – Patrons utilisés dans un champ d’un tuple, par ex., «ts.take [:foo, nil]», «ts.take [/(foo|bar)$/, "abc"]», «ts.take [:foo, Fixnum, /abc/]», etc. : Matche n’importe quel objet Ne peut pas être utilisé à la 1ère position (clé) /pat/ Matche n’importe quel objet qui matche l’expression régulière /pat/ NomDeClasse Matche n’importe quel objet de la classe NomDeClasse (kind_of?(NomDeClasse)) n1..n2 Matche un entier qui fait partie du Range indiqué valeur Matche la valeur spécifique indiquée (égalité avec «==») nil Pour plus de détails sur les patrons, voir les fichiers lib/tuplespace/tuple_pattern. rb et spec/tuple_pattern_spec.rb. 4 Ainsi que dans les méthodes watch, unwatch et each : voir lib/tuplespace/tuplespace.rb. INF5171 (gr. 20) Devoir #2 (Automne 2016) 4 Un exemple de programme «Hello World! » Le Programme Ruby 1 présente le contenu du fichier bin/hello.rb, un programme de style «Hello World! » utilisant un espace de tuples. Voici un exemple d’exécution de ce programme : $ = bin / hello . rb 5 Hello du thread 2 Hello du thread 4 Hello du thread 1 Hello du thread 3 Hello du thread 0 FIN DU PROGRAMME Ce programme illustre diverses utilisations des tuples d’un espace de tuples : • :num_thread : Pour représenter une variable que l’on doit incrémenter de façon atomique — on retire le tuple pour obtenir sa valeur courante, puis on écrit un nouveau tuple avec la valeur modifiée. • :verrou: Pour représenter un verrou d’exclusion mutuelle — ici, pour assurer que les instructions puts, qui ne sont pas atomiques, s’exécutent sans interférence. • :termine : Pour envoyer un signal de synchronisation de chacun des travailleurs vers le coordonnateur de façon à indiquer la terminaison.5 5 Dans cet exemple, pour assurer la terminaison propre et correcte, on aurait aussi pu conserver les descripteurs de thread, puis faire des appels à join sur ces descripteurs. INF5171 (gr. 20) Devoir #2 (Automne 2016) 5 Programme Ruby 1 Un programme «Hello World! » avec un espace de tuples. # !/ usr / bin / env ruby require_relative ’ ../ lib / tuplespace ’ Thread . abort_on_exception = true # E n c a s d ’ e r r e u r d a n s l e s t h r e a d s ! ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Methode executee par chacun des threads . ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def travailleur ( ts ) # On o b t i e n t le p r o c h a i n numero d ’ i d e n t i f i c a t i o n . _ , mon_num = ts . take [: num_thread , Fixnum ] ts . put [: num_thread , mon_num + 1] # On fait le " t ra v a i l "... de facon a t o m i q u e sleep rand ts . take [: verrou ] puts " - Hello du thread #{ mon_num } " ts . put [: verrou ] # On i n d i q u e qu ’ on a t e r m i n e . ts . put [: termine ] end ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Programme principal . ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # nb_threads = ARGV . empty ? ? 10 : ARGV . shift . to_i # On lance les threads , en s p e c i f i a n t l ’ espace de tuples a u t i l i s e r . ts = TupleSpace . create ts . put [: num_thread , 0] nb_threads . times do Thread . new { travailleur ( ts ) } end ts . put [: verrou ] # On attend que tous les t h r e a d s aient t e rm i n e . nb_threads . times do ts . take : termine end puts " = FIN DU PROGRAMME " INF5171 (gr. 20) Devoir #2 (Automne 2016) 6 Ce que vous devez faire Divers fichiers vous sont fournis, sous forme d’un dépôt git : $ git clone http://www.labunix.uqam.ca/~tremblay/git/TupleSpace.git 1. Vous devez compléter les méthodes de la classe TupleSpace de façon à satisfaire les tests unitaires qui vous sont fournis. 2. Vous devez compléter le programme lib/wc.rb, qui utilise un espace de tuples pour réaliser la même tache que l’exemple présenté dans les notes de cours — Sections 5.5.1 et 5.5.3. La documentation des méthodes de la classe TupleSpace, en format yard, est disponible à l’adresse suivante : http://www.labunix.uqam.ca/~tremblay/INF5171/Devoirs/TupleSpaceDoc/ Votre mise en oeuvre de TupleSpace ne doit utiliser que les classes et méthodes de base de Ruby, donc les classes Thread, Mutex, ConditionVariable, etc. — c’est-à-dire les éléments présentés dans le chapitre 6 des notes de cours. Vous ne devez donc pas utiliser les méthodes de la bibliothèque pruby! Quelle machine vous devez utiliser Les tests pour la correction seront exécutés sur la machine japet.labunix.uqam.ca, avec jruby, qui fournit des «vrais» threads parallèles. Par contre, comme vous n’utiliserez que les classes de base, vous devriez pouvoir développer votre code avec n’importe quel Ruby. Or, il faut savoir que le lancement d’un programme (de tests ou autre) avec jruby est nettement plus long que le lancement du même programme avec ruby/MRI. Voici donc une suggestion quant à la façon de procéder pour développer et tester vos méthodes, sachant que c’est ruby/MRI qui est installé sur malt.labunix.uqam.ca alors que c’est jruby qui est installé sur japet.labunix.uqam.ca : 1. Commencez par tester votre(vos) méthode(s) sur malt, avec ruby/MRI — les tests s’exécutent rapidement, donc vous pourrez les exécuter souvent et obtenir rapidement du feedback. 2. Lorsqu’un groupe tests s’exécute avec succès sur malt, exécutez alors le même groupe de tests sur japet avec jruby — donc avec des «vrais» threads parallèles. INF5171 (gr. 20) Devoir #2 (Automne 2016) 7 Ce qui vous est fourni Plusieurs fichiers vous sont fournis que vous n’avez pas à modifier — sauf, évidemment, le fichier lib/tuplespace/tuplespace.rb : 1. lib/debug.rb : Méthodes pour aider au débogage, notamment une méthode jiggle. 2. lib/dbc.rb : Méthodes pour l’approche Design By Contract (DBC), donc pour exprimer des pré-conditions, post-conditions, invariants et assertions. 3. lib/tuplespace/tuple_pattern.rb : La classe TuplePattern et ses diverses méthodes, dont la plus importante, la méthode «=˜». 4. spec/*_spec.rb : Diverses suites de tests unitaires définies à l’aide de MiniUnit — voir plus bas pour les cibles de test, telles qu’identifiées par «rake -T». 5. Quelques exemples programmes qui utilisent un espace de tuples : • bin/hello.rb • bin/premiers.rb • lib/wc.rb (à compléter!) 6. Rakefile, où les principales cibles sont les suivantes (sortie produite par «rake -T») : rake rake rake rake rake rake rake rake test concurrent create_et_put push_et_each take_avec_match take_et_read tuple_pattern watch # # # # # # # # Run tests Tests concurrents des methodes put et take Tests (sequentiels) de create et put Tests (concurrents) de push (<<) et each Tests (sequentiels) de take avec patrons Tests (sequentiels) de take et read Tests du pattern matching des tuples Tests de watch et unwatch rake hello rake premiers rake wc # Tests pour hello world # Tests de la generation des nombres premiers # Tests pour wc rake remise # Remise du travail avec oto C’est la variable WIP (Work In Progress) qui indique la suite de tests à exécuter par défaut — donc lorsqu’on exécute simplement la commande «rake». Initialement, c’est la suite de tests create_et_put qui est active. INF5171 (gr. 20) Devoir #2 (Automne 2016) 8 Ce que vous devez remettre Remise papier Vous devez remettre un document papier (dans la boîte du secrétariat du département) contenant simplement le listage du votre fichier lib/tuplespace/tuplespace.rb — et uniquement ce fichier! Pour la remise de ce document papier, vous devez utiliser la page couverture (avec grille de correction) disponible à la fin du présent du document. Remise électronique Vous devez remettre une version électronique du fichier lib/tuplespace/tuplespace.rb en exécutant la commande suivante sur japet.labunix.uqam.ca : $ rake remise Note : Vous devez auparavant modifier la variable CODES_PERMANENTS dans le Rakefile pour indiquer vos codes permanents (si vous travaillez en équipe, deux personnes maximum) ou votre code permanent (si vous travaillez seul). INF5171 (gr. 20) Devoir #2 (Automne 2016) 9 Remarques sur la correction • Si le fichier remis contient des erreurs de syntaxe, alors vous perdrez une très (très!) grande partie des points — voir plus bas. • Une partie des points sera accordée pour la qualité et le style de votre code : présentation, clarté et simplicité, structure, choix des identificateurs, respect des conventions Ruby,6 etc. Par contre, même si la présence de commentaires est suggérée, je n’évaluerai pas la présence, ou l’absence, de tels commentaires. Deux principes de base pour la clarté du code : KISS et DRY.7 Autre principe pour la correction du style : plus je mets de rouge parce que je ne comprends pas le code ou parce que le code est mal écrit, plus la note est faible / • J’effectuerai la vérification du bon fonctionnement avec d’autres tests que ceux qui vous sont fournis — donc avec des tests privés additionnels. En gros, la répartition des points sera la suivante : compilation correcte ≈ 20 %, bons résultats sur les tests publics ≈ 60 %, bons résultats sur les tests privés ≈ 20 %. Suggestions et indices • La correction des travaux se fera sur la machine japet, avec jruby. Donc, vous devez absolument vous assurer que votre programme fonctionne correctement sur cette machine avant de le remettre. • N’hésitez pas à introduire des méthodes auxiliaires — gardez votre code DRY, c’està-dire, éviter le plus possible le même code qui se répète. • Utilisez git pour gérer l’évolution de votre travail et éviter sa régression, puisque le code qui vous est fourni est déjà sous forme d’un dépôt local git. Donc, lorsque vous avez réussi à faire fonctionner une partie de votre code, faites un commit! Plus de détails sur git sont disponibles via la page suivante : http://www.labunix.uqam.ca/~tremblay/INF5171/Liens/ 6 7 https://github.com/styleguide/ruby KISS = Keep It Simple, Stupid ; DRY = Don’t Repeat Yourself. Travail remis à Guy Tremblay INF5171-20 : Devoir 2 À remettre au plus tard Mardi, 22 novembre, 13h30 Ne pas mettre dans une enveloppe Nom Prénom Code permanent Courriel Nom Prénom Code permanent Courriel Qualité du code (KISS & DRY, respect des conventions Ruby) create_et_put_spec.rb take_et_read_spec.rb take_avec_match_spec.rb push_et_each_spec.rb concurrent_spec.rb {hello,premiers}_spec.rb wc_spec.rb (et lib/wc.rb) / 10 Total /5 /5 /5 /5 /5 /5 /5 /5 / 45 Note globale / 10 Bonus : watch_spec.rb