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

Algorithmes et structures de données Discussion :

Calcul rapide d'une gaussienne.


Sujet :

Algorithmes et structures de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut Calcul rapide d'une gaussienne.
    Bonjour,

    je calcule une valeur gaussienne de la manière suivante :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    private double gaussian(double x, double y, double sig)
    	{
    	return Math.exp(-(x*x+y*y)/(2*sig*sig)) / (2.0*Math.PI*sig*sig) ;
    	}
    Seulement cette fonction est appelées des millions de fois, donc je souhaiterai savoir s'il n'y a pas un moyen plus rapide de faire le calcul. Bon à vrai dire je serai surpris que oui.

    J'avais pensé à :
    - pré-calculer des valeurs, mais les paramètres x, y et sig sont TRES variables.
    - faire des approximations car si x et y sont grands, le résultat est quasi nul.

    Merci par avance...


    PS : quelle est la complexité de la fonction Math.exp() ?
    En gros, est elle très gourmande en terme de CPU ?
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  2. #2
    Membre très actif
    Profil pro
    chercheur
    Inscrit en
    Avril 2004
    Messages
    830
    Détails du profil
    Informations personnelles :
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Avril 2004
    Messages : 830
    Par défaut
    La fonction est calculée par le FPU du processeur et doit prendre le temps de quelques multiplications. Mon PC en calcule 20 millions en environ 2sec.

  3. #3
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    On peut approximer exp() en utilisant des hack sur la représentation en flottant, si les valeurs sont assez petites.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public static double exp(double val) {
    	long hack = (long) (1512775 * val) + 1072632447;
    	return Double.longBitsToDouble(hack << 32);
    }

    On peut aussi utiliser interpoler une table de valeurs précalculées.
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    static double[] EXPNEGTABLE = new double[1000];
    static {
    	for(int i=0;i<1000;i++)
    		EXPNEGTABLE[i]=Math.exp((double)-i/32);
    }
     
    public static double exp(double val) {
    	if (val>0) throw new ArithmeticException(); 
    	int i=(int)(-val*32);
    	if (i>=999) return 0.0;
    	double a=(-val*32)-i;
    	return EXPNEGTABLE[i]+a*(EXPNEGTABLE[i+1]-EXPNEGTABLE[i]);
    }

    Hormis faire des approximations, je ne pense pas qu'on puisse accélérer les calculs. La méthode Math.exp() en Java est un appel natif, alors ca va être difficile de faire mieux.
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  4. #4
    Rédacteur

    Homme Profil pro
    Comme retraité, des masses
    Inscrit en
    Avril 2007
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : Suisse

    Informations professionnelles :
    Activité : Comme retraité, des masses
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 2 978
    Par défaut
    Salut!
    Tout d'abord, il est inutile de calculer deux fois 2.0*sig*sig. Si ça n'est pas assez efficace, pourquoi ne pas passer à un langage plus efficace, comme le C, le Fortran ou même Matlab?
    Jean-Marc Blanc

  5. #5
    Membre très actif
    Profil pro
    chercheur
    Inscrit en
    Avril 2004
    Messages
    830
    Détails du profil
    Informations personnelles :
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Avril 2004
    Messages : 830
    Par défaut
    Pour ma curiosité personnelle, combien de temps mets ton ordi à calculer une exponentielle ? Et quel système utilises-tu ?

  6. #6
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut
    Bonsoir,

    Citation Envoyé par pseudocode Voir le message
    On peut approximer exp() en utilisant des hack sur la représentation en flottant, si les valeurs sont assez petites.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public static double exp(double val) {
    	long hack = (long) (1512775 * val) + 1072632447;
    	return Double.longBitsToDouble(hack << 32);
    }

    On peut aussi utiliser interpoler une table de valeurs précalculées.
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    static double[] EXPNEGTABLE = new double[1000];
    static {
    	for(int i=0;i<1000;i++)
    		EXPNEGTABLE[i]=Math.exp((double)-i/32);
    }
     
    public static double exp(double val) {
    	if (val>0) throw new ArithmeticException(); 
    	int i=(int)(-val*32);
    	if (i>=999) return 0.0;
    	double a=(-val*32)-i;
    	return EXPNEGTABLE[i]+a*(EXPNEGTABLE[i+1]-EXPNEGTABLE[i]);
    }

    Hormis faire des approximations, je ne pense pas qu'on puisse accélérer les calculs. La méthode Math.exp() en Java est un appel natif, alors ca va être difficile de faire mieux.
    - 1 - je ne suis pas fan du hack.
    - 2 - en gros il me faut pré-calculer les valeurs de l'exponentielle pour gagner du temps. Mais est ce réellement significatif d'après toi ? Comme tu le dis toi même, c'est du natif derrière.
    Deuxième question : pourquoi diviser par 32 et faire ensuite ce calcul bizarre ?



    Citation Envoyé par FR119492 Voir le message
    Salut!
    Tout d'abord, il est inutile de calculer deux fois 2.0*sig*sig. Si ça n'est pas assez efficace, pourquoi ne pas passer à un langage plus efficace, comme le C, le Fortran ou même Matlab?
    J'avais déjà corrigé le double calcul.
    Je souhaite optimiser ce calcul qui tourne pour une application en java.



    Citation Envoyé par Nebulix Voir le message
    Pour ma curiosité personnelle, combien de temps mets ton ordi à calculer une exponentielle ? Et quel système utilises-tu ?
    Je n'ai pas fait de test :-(
    Je suis sous Mac OS X.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  7. #7
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Citation Envoyé par ToTo13 Voir le message
    - 2 - en gros il me faut pré-calculer les valeurs de l'exponentielle pour gagner du temps. Mais est ce réellement significatif d'après toi ? Comme tu le dis toi même, c'est du natif derrière.
    Deuxième question : pourquoi diviser par 32 et faire ensuite ce calcul bizarre ?
    Avec la table de précalcul tu gagnes un facteur 10 à 15 sur ma machine (Java 6-u21 64bits) . C'est pas négligeable tout de même.

    La division par 32, c'est juste la fréquence d'échantillonnage de la gaussienne.

    table[0] = exp(-0)
    table[1] = exp(-1/32)
    table[2] = exp(-2/32)
    ...
    table[1000] = exp(-1000/32)
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. calcul rapide d'une somme
    Par nant44 dans le forum MATLAB
    Réponses: 2
    Dernier message: 19/11/2009, 13h42
  2. Calcul rapide des valeurs propres d'une matrice creuse
    Par gsagnol dans le forum Mathématiques
    Réponses: 3
    Dernier message: 21/12/2007, 23h37
  3. Calcul rapide de percentiles
    Par benj63 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 08/12/2006, 14h50
  4. Calcul rapide d'une exponentielle ?
    Par progfou dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 13/04/2006, 21h12
  5. Parcours très rapide d'une arborescence ?
    Par Invité dans le forum C++Builder
    Réponses: 7
    Dernier message: 06/05/2005, 09h24

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