Optimisation des Threads (comparaison de fragments d'ADN)
Résolu/Fermé
mikis69
Messages postés
168
Date d'inscription
mardi 26 novembre 2013
Statut
Membre
Dernière intervention
11 février 2019
-
Modifié par mikis69 le 1/11/2016 à 16:55
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019 - 4 nov. 2016 à 00:07
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019 - 4 nov. 2016 à 00:07
A voir également:
- Optimisation des Threads (comparaison de fragments d'ADN)
- Optimisation pc - Accueil - Utilitaires
- Comparaison million milliard - Accueil - Technologies
- Optimisation découpe panneau gratuit - Télécharger - Outils professionnels
- Optimisation windows 10 - Guide
- Glary Utilities : l'outil référence pour entretenir un PC - Télécharger - Nettoyage
2 réponses
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
1 nov. 2016 à 17:35
1 nov. 2016 à 17:35
Bonjour,
Je ne suis pas sûr d'avoir compris en quoi consistait la comparaison de deux fragments d'ADN, mais en tout cas (n-1)! c'est énorme (et faux) ici tu as n fragments d'ADN à comparer à (n-1) autres fragments, soit n(n-1) comparaisons, c'est déjà beaucoup plus accessible, d'autant qu'en réalité tu en as un peu moins puisque quand tu compares A et B tu n'as pas besoin de comparer B et A ensuite.
Bref, threads ou pas threads, thread bien sûr, mais ça ne sert à rien de faire 1000 threads, parce que ta machine a peut-être 4 ou 5 processeurs maximum, donc ça ne sert à rien d'aller au delà d'une dizaine de threads en tout, parce que sinon ils vont passer leur temps à donner la main à quelqu'un d'autre sans jamais avoir de processeur pour eux.
De plus, Java 8 permet déjà de faire ce genre d'opérations tout seul, tu n'as pas à gérer le nombre de threads, ni le Callable pour attendre le résultat final, tu mets tout ça dans un parallelStream et c'est "magique"
En pratique : Aggregate Operations et notamment la rubrique Parallelism
Je ne suis pas sûr d'avoir compris en quoi consistait la comparaison de deux fragments d'ADN, mais en tout cas (n-1)! c'est énorme (et faux) ici tu as n fragments d'ADN à comparer à (n-1) autres fragments, soit n(n-1) comparaisons, c'est déjà beaucoup plus accessible, d'autant qu'en réalité tu en as un peu moins puisque quand tu compares A et B tu n'as pas besoin de comparer B et A ensuite.
Bref, threads ou pas threads, thread bien sûr, mais ça ne sert à rien de faire 1000 threads, parce que ta machine a peut-être 4 ou 5 processeurs maximum, donc ça ne sert à rien d'aller au delà d'une dizaine de threads en tout, parce que sinon ils vont passer leur temps à donner la main à quelqu'un d'autre sans jamais avoir de processeur pour eux.
De plus, Java 8 permet déjà de faire ce genre d'opérations tout seul, tu n'as pas à gérer le nombre de threads, ni le Callable pour attendre le résultat final, tu mets tout ça dans un parallelStream et c'est "magique"
En pratique : Aggregate Operations et notamment la rubrique Parallelism
mikis69
Messages postés
168
Date d'inscription
mardi 26 novembre 2013
Statut
Membre
Dernière intervention
11 février 2019
2 nov. 2016 à 13:12
2 nov. 2016 à 13:12
Après de nombreuses tentatives, je vois que cela fonctionne sur des fichiers de 170 fragments mais sur le fichier à 1617 fragments ça plante :
Exception in thread "main" java.lang.OutOfMemoryError
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
Est-ce une fuite mémoire ou le garbage collector de java qui fait mal son travail ? :(
Exception in thread "main" java.lang.OutOfMemoryError
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
Est-ce une fuite mémoire ou le garbage collector de java qui fait mal son travail ? :(
mikis69
Messages postés
168
Date d'inscription
mardi 26 novembre 2013
Statut
Membre
Dernière intervention
11 février 2019
Modifié par mikis69 le 2/11/2016 à 16:48
Modifié par mikis69 le 2/11/2016 à 16:48
Pour être un peu plus précis car je viens de comprendre d'où cette erreur provient :
Pour chaque alignement, je dois créer un tableau à deux dimensions de int (pratiquement toujours 500 x 500) afin de calculer la matrice (qui sert à aligner les deux fragments). Mais pour que le GC delete la delete à chaque fois, je la remet à null lorsque j'en ai plus besoin..
Et même avec ça, j'obtiens toujours l'erreur après 1h d'execution..
public void alignementSemiGlobal() { m = new int[f1.size() + 1][f2.size() + 1]; Position maxPosition = calcul(); if(maxPosition.getX() == f1.size()) { // Si le maximum est sur la ligne alignementLigne(f1.size(), maxPosition.getY()); } else { // Sinon le maximum est sur la colonne alignementColonne(maxPosition.getX(), f2.size()); } m = null; }
Pour chaque alignement, je dois créer un tableau à deux dimensions de int (pratiquement toujours 500 x 500) afin de calculer la matrice (qui sert à aligner les deux fragments). Mais pour que le GC delete la delete à chaque fois, je la remet à null lorsque j'en ai plus besoin..
Et même avec ça, j'obtiens toujours l'erreur après 1h d'execution..
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
2 nov. 2016 à 17:02
2 nov. 2016 à 17:02
Dans ton code où est ce que tu te sers de m ? Parce que le mettre à null ne sert pas à grand chose si l'objet derrière est toujours utilisé (par un autre thread par exemple).
De plus si ton programme est voué à durer plusieurs heures il faudrait peut être enregistrer tes résultats au fur et à mesure (dans un fichier ou une base de données) plutôt que tout mettre en mémoire.
Remarque : tu peux utiliser des outils du JDK comme jVisualVM pour suivre l'évolution de ton programme en cours d'exécution (nombre de threads, mémoire alloués, avancement du GC, etc)
De plus si ton programme est voué à durer plusieurs heures il faudrait peut être enregistrer tes résultats au fur et à mesure (dans un fichier ou une base de données) plutôt que tout mettre en mémoire.
Remarque : tu peux utiliser des outils du JDK comme jVisualVM pour suivre l'évolution de ton programme en cours d'exécution (nombre de threads, mémoire alloués, avancement du GC, etc)
mikis69
Messages postés
168
Date d'inscription
mardi 26 novembre 2013
Statut
Membre
Dernière intervention
11 février 2019
>
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
2 nov. 2016 à 17:15
2 nov. 2016 à 17:15
m est juste utilisé dans les méthodes alignementLigne et alignementColonne..
Ce tableau a deux dimensions représentent une matrice en fait et n'est utiliser que dans un thread (fin chaque alignement créera sa propre matrice mais n'en aura plus besoin une fois l'alignement fait) c'est pour cela que je le met à null à la fin (j'ai lu que ca pouvait aider le garbage collector à le jeter pour libérer de la mémoire).
Le soucis c'est que j'aurais besoin de ces données et je ne pense pas que les stocker dans un fichier puisse m'aider car ça risque de compliquer énormément le code..
J'ai déjà une liste de 1617 fragments et chaque fragment possède deux listes :
l'objet 1 de la liste des 1617 fragments aura :
- une liste d'alignements de 1616 alignements (vu qu'il est comparé au 1616 autres)
- une liste d'alignements inverses de 1616 aussi..
l'objet 2 en aura 1615 * 2
Tu penses que java ne peut pas stocker autant de données dans sa mémoire ? C'est la première fois que je suis confronté à un projet qui manipule autant de données.. (et je ne peux pas utiliser de base de données)..
Ce tableau a deux dimensions représentent une matrice en fait et n'est utiliser que dans un thread (fin chaque alignement créera sa propre matrice mais n'en aura plus besoin une fois l'alignement fait) c'est pour cela que je le met à null à la fin (j'ai lu que ca pouvait aider le garbage collector à le jeter pour libérer de la mémoire).
Le soucis c'est que j'aurais besoin de ces données et je ne pense pas que les stocker dans un fichier puisse m'aider car ça risque de compliquer énormément le code..
J'ai déjà une liste de 1617 fragments et chaque fragment possède deux listes :
private List<Alignement> alignements; private List<Alignement> alignementsInverses;
l'objet 1 de la liste des 1617 fragments aura :
- une liste d'alignements de 1616 alignements (vu qu'il est comparé au 1616 autres)
- une liste d'alignements inverses de 1616 aussi..
l'objet 2 en aura 1615 * 2
Tu penses que java ne peut pas stocker autant de données dans sa mémoire ? C'est la première fois que je suis confronté à un projet qui manipule autant de données.. (et je ne peux pas utiliser de base de données)..
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
2 nov. 2016 à 17:28
2 nov. 2016 à 17:28
Ce n'est pas Java le problème, en 64 bits la consommation mémoire qu'il peut théoriquement utiliser est gigantesque, mais c'est ton système d'exploitation qui va limiter la vraie mémoire utilisable.
Remarque : à partir de 6/8 Go le temps nécessaire pour faire un GC va induire des arrêts de services du programme sur des durées perceptibles (même si dans ton cas ça ne va pas changer grand chose)
Soit tu utilises une configuration mémoire par défaut insuffisante et il faut l'augmenter en précisant l'option XmX.
Soit tu es déjà effectivement au max et il faut voir si tu as une vraie fuite mémoire, avec jvisualvm tu auras une idée de la consommation réelle de ton programme et tu verras peut être une aberration.
En complément tu peux faire des hprof de temps en temps pour identifier si les objets qui consomment la mémoire sont bien ceux auxquels tu penses.
Remarque : à partir de 6/8 Go le temps nécessaire pour faire un GC va induire des arrêts de services du programme sur des durées perceptibles (même si dans ton cas ça ne va pas changer grand chose)
Soit tu utilises une configuration mémoire par défaut insuffisante et il faut l'augmenter en précisant l'option XmX.
Soit tu es déjà effectivement au max et il faut voir si tu as une vraie fuite mémoire, avec jvisualvm tu auras une idée de la consommation réelle de ton programme et tu verras peut être une aberration.
En complément tu peux faire des hprof de temps en temps pour identifier si les objets qui consomment la mémoire sont bien ceux auxquels tu penses.
mikis69
Messages postés
168
Date d'inscription
mardi 26 novembre 2013
Statut
Membre
Dernière intervention
11 février 2019
>
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
2 nov. 2016 à 17:40
2 nov. 2016 à 17:40
J'avais lu que l'on pouvait augmenter la mémoire mais que ça ne règle pas le problème. Et si je le fais sur ma machine, lorsque je vais rendre mon projet et que mon professeur l'executera, il va tomber sur une erreur n'est ce pas ? (vu que lui n'aura pas augmenter la taille de sa mémoire)
Je suis entrain de l'exécuter avec Java Monitor et la Used Heap Memory ne dépasse jamais 200 M
Le nombre de threads est constant : 50
Et le CPU est généralement très bas..
Je ne vois vraiment pas à quel moment il peut planter..
Je suis entrain de l'exécuter avec Java Monitor et la Used Heap Memory ne dépasse jamais 200 M
Le nombre de threads est constant : 50
Et le CPU est généralement très bas..
Je ne vois vraiment pas à quel moment il peut planter..
1 nov. 2016 à 19:11
Maintenant que tu le dis, je pense que je me suis trompé c'est plutôt n(n-1) oui .. Car le fragment 1 va générer 1616 comparaisons * 2 (puisqu'il faut tenir compte du fragment inversé/complémentaire)
Et le fragment 2 en générera 1615 * 2.. Donc oui du n(n-1) désolé !
J'avais lu sur internet que nos ordinateurs pouvaient supporter des milliers de threads pourtant.. Donc une dizaine de thread d'accord ! Je vais me renseigner sur les objet que tu m'as donné et je vais les essayer !
Un grand merci pour ta réponse :)
1 nov. 2016 à 20:28
c.getFragments().parallelStream()...........
Mais on utilise cela pour faire des opérations "simples" non ? Genre trouver le max, le min, filtrer des listes.. Mais ici j'aimerais faire pour chaque fragment de la liste :
for(int j = i + 1; j < fragments.size(); j++) { // Sans savoir si je pourrais récupérer l'indice i
f.alignement(fragments.get(j));
}
Ou bien il existe un objet ParallelStream ? Car je ne vois pas trop sinon comment utiliser ces "objets"..
Modifié par mikis69 le 1/11/2016 à 23:02
Avec ce code, tout fonctionne bien.. Dès demain, je poste le temps qu'il faut pour aligner les 1617 fragments !
Merci KX ;)
2 nov. 2016 à 07:35
Oui, mais ils ne vont pas tous travailler en même temps, il leur faut du temps processeur, donc si tu fais 1000 processus il y en au moins 990 qui vont dormir sans rien faire pendant que les autres s'exécutent, et ça coûte (un peu) cher de changer de threads donc il vaut mieux éviter.
Remarque : à voir si tu ne peux pas paralléliser la boucle for avec un deuxième stream parce que à vue de nez ça pourrait se faire.
2 nov. 2016 à 09:20
Merci pour ces bonnes remarques !