TP-systemes-concurrents/TP5/max/MaxTab.java
2023-06-21 20:19:26 +02:00

193 lines
6.9 KiB
Java

//v0.1.2 15/11/21 (PM) (0.1.2 : modification (mineure) des parties à compléter)
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.concurrent.ExecutionException;
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class MaxLocal implements Callable<Integer> {
// pool fixe
private int début;
private int fin;
private int[] tableau;
MaxLocal(int[] t, int d, int f) {
this.début = d;
this.fin = f;
this.tableau = t;
}
@Override
public Integer call() { // le résultat doit être un objet
int ml = 0;
for (int i = début; i < fin; i++) {
if (tableau[i] > ml) {
ml = tableau[i];
}
}
return ml;
}
}
class TraiterFragment extends RecursiveTask<Integer> {
// pool fork-join
private int début;
private int fin;
private int[] tableau;
static int seuil;
private int max = 0;
TraiterFragment(int[] t, int d, int f) {
début = d;
fin = f;
tableau = t;
}
protected Integer compute() {
int resteAFaire = this.fin - this.début;
if (resteAFaire > TraiterFragment.seuil) {
// System.out.println("Décomposition de resteAFaire : " + resteAFaire);
TraiterFragment sp1 = new TraiterFragment(tableau, début, début + resteAFaire / 2);
TraiterFragment sp2 = new TraiterFragment(tableau, début + resteAFaire / 2, fin);
sp1.fork();
sp2.fork();
return Math.max(sp1.join(), sp2.join());
} else {
// System.out.println("Traitement direct de resteAFaire : " + resteAFaire);
return new MaxLocal(tableau, début, fin).call();
}
}
}
public class MaxTab {
// --------- Mono
static int maxMono(int[] t) {
int max = 0;
for (int i = 0; i < t.length; i++) {
max = Math.max(t[i], max);
}
return max;
}
// -------- Pool Fixe
static int maxPoolFixe(ExecutorService xs, int[] t, int nbT) throws InterruptedException, ExecutionException {
List<Future<Integer>> résultats = new LinkedList<Future<Integer>>();
int max = 0; // on suppose que les entiers à trier sont positifs
int grain = Math.max(1, t.length / nbT); /*
* taille d'une recherche locale = taille du tableau/nombre de tâches
* soumises (ou 1 dans le cas (aberrant) où il y a plus de tâches que
* d'éléments du tableau)
*/
return max;
}
// -------- Pool ForkJoin
static int maxForkJoin(ForkJoinPool f, int[] t) {
TraiterFragment tout = new TraiterFragment(t, 0, t.length - 1);
return tout.compute();
}
// -------- main
public static void main(String[] args)
throws InterruptedException, ExecutionException, IOException, FileNotFoundException {
int nbOuvriersPool = 0; // nb ouvriers du pool fixe. Bonne valeur : nb de processeurs disponibles
int nbEssais = -1;
int nbTâches = -1;
int tailleTronçon = -1; // nb d'éléments du tableau traités par chaque ouvrier (FJ)
String chemin = "";
int[] tableau;
long départ, fin;
int max;
long[] tempsMono, tempsPool, tempsForkJoin;
if (args.length == 5) { // analyse des paramètres
chemin = args[0];
try {
nbEssais = Integer.parseInt(args[1]);
nbTâches = Integer.parseInt(args[2]);
tailleTronçon = Integer.parseInt(args[3]);
nbOuvriersPool = Integer.parseInt(args[4]);
} catch (NumberFormatException nfx) {
throw new IllegalArgumentException("\nUsage : MaxTab <fichier> <nb essais>"
+ " <nb tâches (pool)> <taille tronçon (FJ)>" + " <nb ouvriers du pool (pool)>\n"
+ " * <nb tâches (pool)> = nb de fragments à traiter \n"
+ " * <taille tronçon (FJ)> = taille du fragment \n");
}
}
if ((nbEssais < 1) || (nbTâches < 1) || (tailleTronçon < 1) || (nbOuvriersPool < 1)
|| !Files.isRegularFile(Paths.get(chemin), LinkOption.NOFOLLOW_LINKS))
throw new IllegalArgumentException(
"\nUsage : MaxTab <fichier> <nb essais>" + " <nb tâches (pool)> <taille tronçon (FJ)>"
+ " <nb ouvriers du pool (pool)>\n" + " * <nb tâches (pool)> = nb de fragments à traiter \n"
+ " * <taille tronçon (FJ)> = taille du fragment \n");
// appel correct
tempsMono = new long[nbEssais];
tempsPool = new long[nbEssais];
tempsForkJoin = new long[nbEssais];
tableau = TableauxDisque.charger(chemin);
System.out.println(Runtime.getRuntime().availableProcessors() + " processeurs disponibles pour la JVM");
// créer un pool avec un nombre fixe d'ouvriers
ExecutorService poule = Executors.newFixedThreadPool(nbOuvriersPool);
// créer un pool ForkJoin
ForkJoinPool fjp = new ForkJoinPool();
TraiterFragment.seuil = tailleTronçon;
for (int i = 0; i < nbEssais; i++) {
départ = System.nanoTime();
max = maxMono(tableau);
fin = System.nanoTime();
tempsMono[i] = (fin - départ);
System.out
.println("Essai [" + i + "] : maximum = " + max + ", durée (mono) " + tempsMono[i] / 1_000 + "µs");
}
System.out.println("--------------------");
for (int i = 0; i < nbEssais; i++) {
départ = System.nanoTime();
max = maxPoolFixe(poule, tableau, nbTâches);
fin = System.nanoTime();
tempsPool[i] = (fin - départ);
System.out
.println("Essai [" + i + "] : maximum = " + max + ", durée (pool) " + tempsPool[i] / 1_000 + "µs");
}
poule.shutdown();
System.out.println("--------------------");
for (int i = 0; i < nbEssais; i++) {
départ = System.nanoTime();
max = maxForkJoin(fjp, tableau);
fin = System.nanoTime();
tempsForkJoin[i] = (fin - départ);
System.out.println(
"Essai [" + i + "] : maximum = " + max + ", durée (FJ) " + tempsForkJoin[i] / 1_000 + "µs");
}
System.out.println("--------------------");
}
}