INF5171: Laboratoire #9 Variables atomiques en Java et Algorithme

publicité
INF5171: Laboratoire #9
Variables atomiques en Java
et
Algorithme SPMD pour le calcul du minimum
26 novembre 2015
13h30–15h30
PK-S1575
Le premier exercice de ce labo a pour but de vous familiariser avec l’utilisation des
variables atomiques Java, alors que le deuxième exercice a pour but de vous familiariser
avec la technique utilisée en OpenCL — modèle SIMT, donc semblable en partie au modèle
SPMD — pour effectuer des réductions.
1
Géneration thread-safe de nombres pseudo-aléatoires
à l’aide de variables atomiques
Pour cet exercice, vous devez obtenir le code source comme suit :
$ git clone http://www.labunix.uqam.ca/~tremblay/git/PseudoRandom.git
Le programme Java 1 définit une interface qui spécifie une opération pour générer un
nombre pseudo-aléatoire, alors que le programme Java 2 définit une classe utilitaire et
une méthode statique pour générer un nombre «pseudo-aléatoire» à l’aide d’une méthode
arithmétique simple. Quant au programme Java 3, il définit une classe qui met en oeuvre l’opération prochainInt de l’interface PseudoRandom, et ce en utilisant la méthode
prochain de la classe UtilPseudoRandom.
Le problème avec la classe PseudoRandomSeq est qu’elle ne peut pas être utilisée par
des threads, puisque la section critique — la mise à jour de la variable d’instance prochain
— n’est pas protégée. Cette classe et méthode ne sont donc pas thread-safe
/
1
Programme Java 1 Interface PseudoRandom.
interface PseudoRandom {
// Retourne un entier pseudo -aleatoire compris entre 0 et n-1;
int prochainInt ( int n );
}
Programme Java 2 Classe UtilPseudoRandom.
public class UtilPseudoRandom {
final static private int A = 129;
final static private int B = 13;
public static int prochain ( int v ) {
return Math . abs ( A * v + B );
}
}
Programme Java 3 Classe PseudoRandomSeq.
public class PseudoRandomSeq implements PseudoRandom {
private int prochain ;
public PseudoRandomSeq ( int germe ) {
this . prochain = germe ;
}
public int prochainInt ( int n ) {
int resultat = prochain % n ;
prochain = UtilPseudoRandom . prochain ( prochain );
return resultat ;
}
}
Ce que vous devez faire
a. Complétez la mise en oeuvre de la classe PseudoRandomLock qui met en oeuvre
l’interface PseudoRandom mais de façon thread-safe. Cette mise en oeuvre doit utiliser
un ReentrantLock pour protéger la section critique.
Remarque : Pour désactiver temporairement un test — par ex., désactiver le test
pour la version PseudoRandomAtomic pendant que vous travaillez sur la première
version ou pour désactiver temporairement les tests avec les threads — il suffit de
mettre l’annotation @Ignore devant @Test.
b. Complétez la mise en oeuvre de la classe PseudoRandomAtomic qui met en oeuvre l’interface PseudoRandom, là aussi de façon thread-safe. Par contre, cette mise
en oeuvre ne doit pas utiliser de verrous ; elle doit plutôt utiliser une variable atomique : cf. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/
atomic/AtomicInteger.html
c. Dans le programme de tests TesterPR, complétez la méthode runVersionAvecThreads
pour que le test s’effectue avec des vrais threads.
Note : N’essayez pas de vérifier que la suite de nombres pseudo-aléatoire générée par
une version parallèle est exactement la même que celle générée par la version séquentielle — ce ne serait pas possible puisque les threads vont s’exécuter dans un ordre
arbitraire. Vérifiez simplement que les ensembles de nombres générés sont les
mêmes — cf. http://www.tutorialspoint.com/java/util/arrays_sort_int.htm
d. Complétez le programme Benchmarks.java pour comparer les performances entre
les versions PseudoRandomLock et PseudoRandomAtomic par rapport à la version
PseudoRandomSeq.
Que constatez-vous?
2
Approche SPMD pour le calcul du minimum
Pour cet exercice, vous devez obtenir le code source comme suit :
$ git clone http://www.labunix.uqam.ca/~tremblay/git/MinSPMD.git
La méthode Array#pmin dans le fichier array.rb calcule le minimum d’un tableau en
utilisant une technique parallèle dite «par dédoublement récursif».
a. Expliquez comment fonctionne cette méthode et pourquoi elle retourne bien la valeur
minimum. Voyez-vous le lien avec l’approche récursive? Est-ce que cela vous semble
une approche efficace — en termes d’utilisation des processeurs?
Note : Pour simplifier le code et l’analyse, on suppose que la taille du tableau à
traiter est une puissance de 2!
b. La méthode pmin lance des threads de façon répétitive — pour initialiser le tampon,
puis dans la boucle while.
Complétez la méthode pmin_pram pour que les threads soient lancés une et une seule
fois — donc dans le style SPMD. Vous pouvez évidemment utiliser la classe Barriere.
Téléchargement