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 :

FFT inverse, algorithme adapté ?


Sujet :

Algorithmes et structures de données

  1. #1
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut FFT inverse, algorithme adapté ?
    Bonsoir à tout le monde !
    J'ai un algorithme de fft inverse, mais il ne me parait pas adapté à mon architecture (les multiplications mettent plus de temps que les additions, au moins 5 fois plus). Il semblerait que ce soit le radix (mais avec un programme pas commenté...). Je pex fournir un bout de code correspondant, si nécessaire, mais ce que je cherche c'est surtout tous les algos qui existent, qui font un calcul de fft inverse complexe, avec le moins de multiplications possibles...

    Merci d'avance pour vos réponses !
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  2. #2
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    j'uitilise la + part du temps l'algorithme de Cooley-Tukey qui est en n.log(n).
    L'algorithme de Winograd [WFTA] permet de réduire sensiblement le nombre de multiplications par contre il necessite plus de mise en forme des data.

  3. #3
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    Voilà un bout de l'algo que j'ai :
    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
     
            bg = fftn >> 3;                 /* 128 or 64 >> 3 */
            gp = 4;                         /* groups per pass */
     
            for (k = fftnlg2m3; k != 0; k--)
            {
                bfyrptr1 = fftrptr;
                bfyiptr1 = fftiptr;
                bfyrptr2 = fftrptr + bg;
                bfyiptr2 = fftiptr + bg;
                brxcosptr = brxcos;
                brxsinptr = brxsin;
     
                for (j=gp ; j!=0 ; j++) {
                    cr = *brxcosptr;
                    brxcosptr++;
                    ci = *brxsinptr;
                    brxsinptr++;
     
                    for (i = bg; i !=0 ; i--)
                    {
                        ar = *bfyrptr1;
                        ai = *bfyiptr1;
                        br = *bfyrptr2;
                        bi = *bfyiptr2;
     
                        rtemp = br*cr - bi*ci;
                        itemp = br*ci + bi*cr;
     
                        *bfyrptr1 = (ar - rtemp);
                        bfyrptr1++;
                        *bfyiptr1 = (ai - itemp);
                        bfyiptr1++;
                        *bfyrptr2 = (ar + rtemp);
                        bfyrptr2++;
                        *bfyiptr2 = (ai + itemp);
                        bfyiptr2++;
                    }
                    bfyrptr1 += bg;
                    bfyiptr1 += bg;
                    bfyrptr2 += bg;
                    bfyiptr2 += bg;
                }
                bg >>= 1;
                gp <<= 1;
            }
    En voyant bien que les brxcos/sin sont des pointeurs sur des tableaux de cos/sin précalculés...

    Mon problème ne situe pas dans la compréhension du code (ce ne serait pas le bon forum ) mais dans l'amélioration.
    Je ne connais pas Winograd, mais je vais me renseigner. Les données ont vraiment besoin de beaucoup de mise en forme ?
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  4. #4
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Points : 460
    Points
    460
    Par défaut
    Quelle architecture utilises-tu ? (Moi je connais que Intel)

    Ton algorithme utilise de toute évidence un radix de 2.
    A titre de comparaison, tu trouveras ci-après mon implémentation en C++ de la FFT à radix 2, facilement transposable ce C.

    Un truc qui pourrait améliorer la vitesse de ton implémentation :
    Faire des vecteurs de complexes (RIRIRI…) plutôt que 2 vecteurs de réels (RRR…, III…)
    => moins de pointeurs à gérer (2 au lieux de 4, ça peut faire une grande différence sur un Pentium), peut-être moins d’accès mémoire…

    Pour des implémentations beaucoup plus performantes, il faut augmenter le radix, et utiliser les instructions parallèles (SSE, SSE2, SSE3 pour les Pentiums).
    Mon implémentation perso:
    => www.ient.rwth-aachen.de/team/laurent/genial/genial.html
    Mais FFTW est plus connue :
    => http://www.fftw.org

    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
    template<class G>
    Vector<G> &complex_radix2_fft_in_place(Vector<G> &X)
    {
      typedef Vector<G> array_type;
      typedef typename array_type::size_type size_type;
      typedef PROMOTE2(complex<float>,typename array_type::value_type) value_type;
      typedef PROMOTE2(complex<float>,typename value_type_traits<value_type>::value_type) complex_type;
      typedef typename complex_type::value_type real_type;
     
      size_type n = X.size();
     
      assert(log2n(n)>=0);
     
      bitreverse_order(X);
     
      for (int dual=1; dual<n; dual*=2)
      {
        real_type theta = -PI/dual;
        real_type s  = sin(theta);
        real_type s2 = real_type(2)*sqr(sin(real_type(0.5)*theta));
     
        complex_type w(1,0);
     
        value_type wd;
        for (size_t a=0; a<dual; ++a, w+=s*complex_type(-w.imag(),w.real())-s2*w)
          for (size_t b=0; b<n; b+=2*dual)
          {
            value_type &Ti=X[b+a];
            value_type &Tj=X[b+a+dual];
            wd=w*Tj;
            Tj=Ti-wd;
            Ti+=wd;
          }
      }
      return X;
    }

  5. #5
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    A priori, recherches à l'appui, l'implémentation serait split-radix.
    L'architecture est un Leon2 (SparcV8).
    Je vois qu'il existe aussi une implémentation du split-radix à 3 mult 3 add au lieu de 4 mult 2 add...
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  6. #6
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Points : 460
    Points
    460
    Par défaut
    Ton "split-radix", c'est peut-être ce que j'appelle "avec radix mixte".
    Ca consiste à décomposer la longueur N en un produit de facteurs.
    Le radix-2 ne permet que des puissances de 2.
    Alors qu'avec un radix mixte permet bien d'autres longueurs, du moment qu'elle se laisse décomposer.
    FFTW et mon implémentation de la FFT utilisent des facteurs allant jusqu'à 64.

    Deux avantages majeurs pour la vitesse:
    1) moins d'opérations
    2) meilleure utilisation des registres => moins d'acces mémoire (goulot d'étranglement, en tout cas pour les Pentiums)

    Inconvénient: plus compliqué

    J'ai pas réfléchi au problème, mais je doute qu'il soit possible de réduire le nombre de multiplications d'une autre façon (si vraiment les Sparcs sont lents par rapport à l'addition). Il existe une limite inférieure théorique dont je ne connais pas la formule.

    Si tu recherches la vitesse, si tu n'est pas obligé d'implémenter, et si la licence te le permet alors FFTW se laisse très probablement compiler sur un Sparc.

    Ca existe les instructions SIMD (calcul parallèle) sur les Sparcs? Très probablement.

  7. #7
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    Hors de question d'utiliser FFTW, question de licence comme tu l'as si justement soupçonné .
    Je peux m'en inspirer, et c'est ce que je fais ^^.
    Maintenant, pour la question de l'existence d'instructions SIMD sur le Sparc, je ne crois pas, mais je ne le maîtrise pas encore assez pour répondre...
    Je suis en plein dans la doc ^^.
    Pour l'algo qui est implémenté, il y a un radix 4 puis un radix 2.
    L'idée de mettre les réels et imaginaires dans le même tableau est à creuser, merci pour cette piste .
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

  8. #8
    Membre éclairé

    Inscrit en
    Juin 2004
    Messages
    1 397
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 1 397
    Points : 763
    Points
    763
    Par défaut
    J'ai trouvé dans le bouquin "The Art of Computer Programming" volume 2 une solution pour faire une multiplication complexe avec seulement 3 multiplications et 5 additions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    (a+bi)(c+di)
    =a(c+d)-(a+b)d+i[a(c+d)+(b-a)c]
    Ca a le mérite d'être facile à montrer...
    Aucune réponse à une question technique par MP.
    Ce qui vous pose problème peut poser problème à un(e) autre

    http://thebrutace.labrute.fr

Discussions similaires

  1. [FFTW3] - FFT Inverse
    Par bobby4078 dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 25/02/2013, 21h07
  2. fft inverse
    Par rochdidz dans le forum Signal
    Réponses: 4
    Dernier message: 15/06/2012, 12h13
  3. FFT inverse
    Par sofiya dans le forum Signal
    Réponses: 9
    Dernier message: 23/05/2007, 15h25
  4. Code source de FFT et FFT inverse pour Delphi
    Par david_chardonnet dans le forum Delphi
    Réponses: 2
    Dernier message: 06/03/2007, 21h46
  5. FFTW : FFT et FFT inverse
    Par Ange44 dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 29/09/2006, 16h32

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