IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Threader une fonction


Sujet :

Langage Java

  1. #1
    Membre éprouvé
    Homme Profil pro
    Ingénieur réseau et sécurité / Consultant
    Inscrit en
    Août 2005
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur réseau et sécurité / Consultant
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2005
    Messages : 1 068
    Par défaut Threader une fonction
    Bonjour à tous,

    Je suis en train de développer une petite classe pour faire différentes opérations mathématiques sur des matrices et j'aimerai threader certaine de mes fonctions comme celle de multiplication de matrice. Voici le code qui fonctionne et qui n'est pas threadé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public Matrix multiply(Matrix m) throws Exception{
     
    		double[][] table = new double[this.getNumberOfLines()][this.getNumberOfColumns()];
    		Matrix res = new Matrix(table);
     
    		int k,i,j;
    		long value = 0;
     
    		for (k=0; k<this.getNumberOfColumns(); k++){
    			for (i=1; i<this.getNumberOfLines()+1; i++){ 
    				for (j=0; j<this.getNumberOfColumns(); j++)
    					value += this.matrix[i-1][j]*m.matrix[j][k];
    				res.matrix[i-1][k] = value;
    				value = 0;
    			}
    		}
    		return res;
    	}
    Quelqu'un pourrait-il m'éguiller sur comment réaliser ce que je désire ?

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    si je devais paralléliser ça, je le ferais de cette manière:

    1) créer un ExecutorService avec un certain nombre de threads
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ExecutorService pool = Executors.newFixedThreadPool(nbThreads);
    2) dans la boucle extérieure, au lieu de mettre les boucle intérieur, mettre en queue sur l'exécutor un Runnable qui fait la partie intérieure. Comme toutes les itérations internes sont indépendantes, ca ne devrais pas poser de soucis.

    3) faire un shutdown du service et attendre (awaitTemination) que toutes les tâches soient effectuées

    4) retourner la valeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    		Matrix res = new Matrix(table);
     
    		int k,i,j;
    		long value = 0;
     
    		for (k=0; k<this.getNumberOfColumns(); k++){
                            pool.execute(new ColumnMultiplication(this,table,res,k));
    			/* a mettre dans columnMultiplication
                            for (i=1; i<this.getNumberOfLines()+1; i++){ 
    				for (j=0; j<this.getNumberOfColumns(); j++)
    					value += this.matrix[i-1][j]*m.matrix[j][k];
    				res.matrix[i-1][k] = value;
    				value = 0;
    			}*/
    		}
                    pool.shutdown();
                    while(true){
                        if (pool.awaitTemination(60,TimeUnit.Seconds))
                           return res;
                    }
    	}

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur réseau et sécurité / Consultant
    Inscrit en
    Août 2005
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur réseau et sécurité / Consultant
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2005
    Messages : 1 068
    Par défaut
    Super merci.

    mais je dois faire une nouvelle classe ColumnMultiplication alors ? je peux le faire en classe interne ou pas ?

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    vous pouvez essayer de la faire en interne, mais vu les données qu'elle utilisera de la méthode, il faudra fournir un constructeur malgré tout

  5. #5
    Membre éprouvé
    Homme Profil pro
    Ingénieur réseau et sécurité / Consultant
    Inscrit en
    Août 2005
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur réseau et sécurité / Consultant
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2005
    Messages : 1 068
    Par défaut
    Voila jai fais avec une classe interne private.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    private class ColumnMultiplication implements Runnable{
    		public ColumnMultiplication(Matrix matrix, double[][] table, Matrix res, int k) {
    			double value = 0;
    			for (int i=1; i < matrix.getNumberOfLines()+1; i++){
    				for (int j=0; j < matrix.getNumberOfColumns(); j++)
    					value += matrix.matrix[i-1][j]*table[j][k];
    				res.matrix[i-1][k] = value;
    				value = 0;
    			}
    		}
     
    		@Override
    		public void run() {
    			// TODO Auto-generated method stub
     
    		}
    	}
    Cette classe est donc interne à ma classe Matrix. Ensuite voici le code de ma méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ExecutorService pool = Executors.newFixedThreadPool(10);
     
    	public Matrix threadedMultiply(Matrix m) throws InterruptedException{
    		Thread t = new Thread();
    		t.start();
    		double[][] table = new double[this.getNumberOfLines()][this.getNumberOfColumns()];
    		Matrix res = new Matrix(table);
     
    		long value = 0;
     
    		for (int k=0; k < this.getNumberOfColumns(); k++){
    			pool.execute(new ColumnMultiplication(this,table,res,k));
    		}
    		pool.shutdown();
            while(true){
                if (pool.awaitTermination(60,TimeUnit.SECONDS))
                   return res;
            }
    	}
    J'ai entendu dire qu'au lieu de mettre un fixed pool de thread, on pouvais automatiser le nombre de threads avec newCachedThreadPool(). Sa apporterai quoi de plus ?

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    il y a une erreur dans votre code. Vous faites le calcul dans le constructeur, c'est à dire dans le thread principal, et vos thread du pool font du "rien" (run vide). Mettez le calcul dans le run, sinon ça sert à rien

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur réseau et sécurité / Consultant
    Inscrit en
    Août 2005
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur réseau et sécurité / Consultant
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2005
    Messages : 1 068
    Par défaut
    Etrange pourtant avec la méthode standard, je fais une multiplication de matrice 1000x1000 en 19 secondes et avec la version threadée comme je l'ai montrée dans mon poste précédent, je fais que 8 secondes...

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    et sur comben de calculs et combien de fois avez vous fait vos mesures?
    Ici vous avez peut etre le JIT qui est intervenu (quoi que je n'arrive pas à reproduire vos mesures avec votre code).

    vous avez appelé 1000 fois une méthode (le constructeur), le JIT a donc eu tout le loisir entre les appel de compiler nativement ce code.

    Si vous ne faite qu'une méthode qui dure 19 secondes, il faudra attendre d'en sortir et l'appel suivant pour avoir une opportunité de compilation native


    Bref c'est peut-être un effet de bord, du simplement au fait que le JIT est intervenu plus tot Ou un erreur de mesure :p

  9. #9
    Membre éprouvé
    Homme Profil pro
    Ingénieur réseau et sécurité / Consultant
    Inscrit en
    Août 2005
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur réseau et sécurité / Consultant
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2005
    Messages : 1 068
    Par défaut
    Vous avez raison. Voici mon code maintenant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    /**
             * This method will calculate the multiplication between two matrix of the same size
             * and return the result in a new matrix
             * @param Matrix m
             * @return Matrix res
             * @throws Exception
             */
    	public Matrix multiply(Matrix m) throws Exception{
    		double[][] table = new double[this.getNumberOfLines()][this.getNumberOfColumns()];
    		Matrix res = new Matrix(table);
     
    		long value = 0;
     
    		for (int k=0; k < this.getNumberOfColumns(); k++){
    			for (int i=1; i < this.getNumberOfLines()+1; i++){
    				for (int j=0; j < this.getNumberOfColumns(); j++)
    					value += this.matrix[i-1][j]*m.matrix[j][k];
    				res.matrix[i-1][k] = value;
    				value = 0;
    			}
    		}
    		return res;
    	}
     
    	/**
             * Make a multiply operation between two matrix. This method is THREADED with a pool of fixed thread. 
             * When you call this method, the second parameter is the number of thread that you want to use.
             * @param Matrix m
             * @param int nbOfThread
             */
    	ExecutorService pool = Executors.newFixedThreadPool(5);
    	public Matrix threadedMultiply(Matrix m, int nbOfThread) throws InterruptedException{
    		double[][] table = new double[this.getNumberOfLines()][this.getNumberOfColumns()];
    		Matrix res = new Matrix(table);
     
    		long value = 0;
     
    		for (int k=0; k < this.getNumberOfColumns(); k++){
    			pool.execute(new ColumnMultiplication(this,table,res,k));
    		}
    		pool.shutdown();
            while(true){
                if (pool.awaitTermination(60,TimeUnit.SECONDS))
                   return res;
            }
    	}
     
    	/**
             * Make a multiply operation between two matrix. This method is THREADED with a pool of cached threads. 
             * @param Matrix m
             */
    	ExecutorService pool2 = Executors.newCachedThreadPool();
    	public Matrix threadedMultiply(Matrix m) throws InterruptedException{
    		double[][] table = new double[this.getNumberOfLines()][this.getNumberOfColumns()];
    		Matrix res = new Matrix(table);
     
    		long value = 0;
     
    		for (int k=0; k < this.getNumberOfColumns(); k++){
    			pool2.execute(new ColumnMultiplication(this,table,res,k));
    		}
    		pool2.shutdown();
            while(true){
                if (pool2.awaitTermination(60,TimeUnit.SECONDS))
                   return res;
            }
    	}
     
    	/**
             * 
             * @author Cyrill Gremaud
             * This internal private class is only here for the treaded multiply method.
             * It implements Runnable interface to manage the threads
             */
    	private class ColumnMultiplication implements Runnable{
    		private Matrix matrix, res;
    		private double[][] table;
    		private int k;
    		public ColumnMultiplication(Matrix matrix, double[][] table, Matrix res, int k) {
    			this.k = k;
    			this.matrix = matrix;
    			this.res = res;
    			this.table = table;
    		}
     
    		@Override
    		public void run() {
    			double value = 0;
    			for (int i=1; i < matrix.getNumberOfLines()+1; i++){
    				for (int j=0; j < matrix.getNumberOfColumns(); j++)
    					value += matrix.matrix[i-1][j]*table[j][k];
    				res.matrix[i-1][k] = value;
    				value = 0;
    			}
    		}
    	}
    Ensuite voici l'appel que je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    	Matrix m1 = new Matrix("/media/Iomega HDD/backup linux/prog_conc/Matrix2/TP-matrix/src/p1/matrice.txt");
    		Matrix m2 = new Matrix("/media/Iomega HDD/backup linux/prog_conc/Matrix2/TP-matrix/src/p1/matrice2.txt");
     
    		System.out.println("Call multiply no-threaded method for a 1000x1000 matrix.");
    		long a = System.currentTimeMillis();
    		Matrix rep = m1.multiply(m2);
    		long b = System.currentTimeMillis();
    		System.out.println("Execution time for no-threaded method : "+(b-a)+" ms");
     
    		System.out.println();
     
    		System.out.println("Call multiply threaded method (fixed pool) for a 1000x1000 matrix.");
    		a = System.currentTimeMillis();
    		rep = m1.threadedMultiply(m2,5);
    		b = System.currentTimeMillis();
    		System.out.println("Execution time for threaded method (fixed pool) : "+(b-a)+" ms");
     
    		System.out.println();
     
    		System.out.println("Call multiply threaded method (cached pool) for a 1000x1000 matrix.");
    		a = System.currentTimeMillis();
    		rep = m1.threadedMultiply(m2);
    		b = System.currentTimeMillis();
    		System.out.println("Execution time for threaded method (cached pool) : "+(b-a)+" ms");
    et voici le résultat

    Call multiply no-threaded method for a 1000x1000 matrix.
    Execution time for no-threaded method : 18690 ms

    Call multiply threaded method (fixed pool) for a 1000x1000 matrix.
    Execution time for threaded method (fixed pool) : 4351 ms

    Call multiply threaded method (cached pool) for a 1000x1000 matrix.
    Execution time for threaded method (cached pool) : 4756 ms
    Vous en pensez quoi ?

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    vous devriez faire tourner ça dans une boucle pendant une 15aine de minutes pour vous assurer que vos mesures sont stables

  11. #11
    Membre expérimenté
    Inscrit en
    Mai 2007
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 335
    Par défaut
    Oui, il faut avoir un échantillon de plusieurs mesures pour faire une moyenne+écart type. Mais pour l'instant les mesures accélération-efficacité ont l'air bonnes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Accélération:
    18690/4351
    =4.2955642381061825
     
    18690/4756
    =3.929772918418839
    Ce qui donne une efficacité=accélération/nbprocesseurs de l'ordre de 1 sur un quad core (à noter qu'une efficacité >1 est en théorie impossible)
    noter également que le 5ème thread ne sert visiblement à rien, il vaudrait mieux initialiser au nombre de core de tes processeurs (2,4,6,8...)

    J'aurais aussi tendance à vérifier que le résultat du calcul est le bon, histoire de valider pleinement ton algo.

    edit:
    http://fr.wikipedia.org/wiki/Acc%C3%...%C3%A9lisme%29

  12. #12
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par deltree Voir le message
    Oui, il faut avoir un échantillon de plusieurs mesures pour faire une moyenne+écart type.
    C'est surtout qu'en java les premières mesures sont souvent non révélatrice des performance une fois que la jvm est "chaude", et ce en raison des nombreuses optimisations au vol qui auront lieu à force d'utiliser les même méthodes

Discussions similaires

  1. Threader la fonction d'une classe
    Par I-DEXX dans le forum C++
    Réponses: 8
    Dernier message: 03/11/2013, 01h07
  2. Comment chronométrer une fonction
    Par 323 dans le forum Pascal
    Réponses: 3
    Dernier message: 19/03/2003, 21h24
  3. [VBA-E] avec une fonction value
    Par laas dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 28/11/2002, 14h22
  4. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 21h14
  5. Une fonction avec des attributs non obligatoires
    Par YanK dans le forum Langage
    Réponses: 5
    Dernier message: 15/11/2002, 14h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo