Changeset 2574 in Sophya


Ignore:
Timestamp:
Jul 29, 2004, 10:40:49 AM (21 years ago)
Author:
cmv
Message:

Optimisation produit de matrice a la sauce cmv 29/07/04

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/SophyaLib/TArray/tmatrix.cc

    r2421 r2574  
    1 // $Id: tmatrix.cc,v 1.24 2003-08-08 13:07:06 ansari Exp $
     1// $Id: tmatrix.cc,v 1.25 2004-07-29 08:40:49 cmv Exp $
    22//                         C.Magneville          04/99
    33#include "machdefs.h"
     
    66#include "pexceptions.h"
    77#include "tmatrix.h"
     8
     9//#define DO_NOT_OPTIMIZE_PRODUCT
    810
    911/*!
     
    411413  \param mm : define the memory mapping type for the return matrix
    412414 */
     415////////////// Routine de base sans optimisation //////////////
     416/*
    413417template <class T>
    414418TMatrix<T> TMatrix<T>::Multiply(const TMatrix<T>& b, short mm) const
     
    437441  return rm;
    438442}
     443*/
     444
     445////////////// Routine optimisee //////////////
     446template <class T>
     447TMatrix<T> TMatrix<T>::Multiply(const TMatrix<T>& b, short mm) const
     448{
     449  if (NCols() != b.NRows())
     450    throw(SzMismatchError("TMatrix<T>::Multiply(b) NCols() != b.NRows() ") );
     451
     452  // Commentaire: pas de difference de vitesse notable selon les mappings choisis pour la matrice produit "rm"
     453  if (mm == SameMemoryMapping) mm = GetMemoryMapping(); 
     454  TMatrix<T> rm(NRows(), b.NCols(), mm);
     455  rm = (T) 0;  // Rien ne garantit que rm soit mise a zero a la creation !
     456
     457  // Les "steps" pour l'adressage des colonnes de A et des lignes de B
     458  sa_size_t stepa = Step(ColsKA());
     459  sa_size_t stepb = b.Step(b.RowsKA());
     460
     461  // On decide si on optimise ou non selon les dimensions de A et B
     462  // (il semble que optimiser ou non ne degrade pas notablement la vitesse pour les petites matrices)
     463#ifdef DO_NOT_OPTIMIZE_PRODUCT
     464  bool no_optim = true;
     465#else
     466  bool no_optim = false;
     467  //NON juste pour memoire: if((stepa+stepb)*NCols()*sizeof(T)<100000) no_optim=true;
     468#endif
     469
     470  // Calcul de C=rm = A*B   (A=*this)
     471  // Remember: C-like      matrices are column packed
     472  //           Fortan-like matrices are line   packed
     473  sa_size_t r,c,k;
     474  T sum;
     475  const T * pe;
     476
     477  // Pas d'optimisation demandee
     478  if( no_optim ) {
     479    //cout<<"no_optim("<<no_optim<<") "<<stepa<<" "<<stepb<<endl;
     480    const T * pea;
     481    const T * peb;
     482    for(r=0; r<rm.NRows(); r++) {     // Boucle sur les lignes de A
     483      for(c=0; c<rm.NCols(); c++) {   // Boucle sur les colonnes de B
     484        sum = 0;
     485        pea = &((*this)(r,0));
     486        peb = &(b(0,c));
     487        // On gagne un peu en remplacant "pea[k*stepa]" par "pea+=stepa" pour les grosses matrices
     488        //for(k=0; k<NCols(); k++)  sum += pea[k*stepa]*peb[k*stepb];
     489        for(k=0; k<NCols(); k++) {sum += (*pea)*(*peb); pea+=stepa; peb+=stepb;}
     490        rm(r,c) = sum;
     491      }
     492    }
     493  }
     494  // A.col est packed  et  B.row est packed (on a interet a optimiser quand meme)
     495  else if(stepa==1 && stepb==1) {
     496    //cout<<"A.col packed && B.row not packed "<<stepa<<" "<<stepb<<endl;
     497     T * pea = new T[rm.NCols()];
     498    const T * peb;
     499    for(r=0; r<rm.NRows(); r++) {     // Boucle sur les lignes de A
     500      pe = &((*this)(r,0));
     501      for(k=0; k<NCols(); k++) {pea[k] = *(pe++);}
     502      for(c=0; c<rm.NCols(); c++) {   // Boucle sur les colonnes de B
     503        sum = 0;
     504        peb = &(b(0,c));
     505        for(k=0; k<NCols(); k++) sum += *(peb++)*pea[k];
     506        rm(r,c) = sum;
     507      }
     508    }
     509    delete [] pea;
     510 }
     511  // A.col est packed  et  B.row n'est pas packed
     512  else if(stepa==1 && stepb!=1) {
     513    //cout<<"A.col packed && B.row not packed "<<stepa<<" "<<stepb<<endl;
     514    const T * pea;
     515    T * peb = new T[rm.NCols()];
     516    for(c=0; c<rm.NCols(); c++) {     // Boucle sur les colonnes de B
     517      pe = &(b(0,c));
     518      for(k=0; k<NCols(); k++) {peb[k] = *pe; pe+=stepb;}
     519      for(r=0; r<rm.NRows(); r++) {   // Boucle sur les lignes de A
     520        sum = 0;
     521        pea = &((*this)(r,0));
     522        for(k=0; k<NCols(); k++) sum += pea[k]*peb[k];
     523        rm(r,c) = sum;
     524      }
     525    }
     526    delete [] peb;
     527  }
     528  // A.col n'est pas packed  et  B.row est packed
     529  else if(stepa!=1 && stepb==1) {
     530    //cout<<"A.col not packed && B.row packed "<<stepa<<" "<<stepb<<endl;
     531    T * pea = new T[rm.NCols()];
     532    const T * peb;
     533    for(r=0; r<rm.NRows(); r++) {     // Boucle sur les lignes de A
     534      pe = &((*this)(r,0));
     535      for(k=0; k<NCols(); k++) {pea[k] = *pe; pe+=stepa;}
     536      for(c=0; c<rm.NCols(); c++) {   // Boucle sur les colonnes de B
     537        sum = 0;
     538        peb = &(b(0,c));
     539        for(k=0; k<NCols(); k++) sum += pea[k]*peb[k];
     540        rm(r,c) = sum;
     541      }
     542    }
     543    delete [] pea;
     544  }
     545  // A.col n'est pas packed  et  B.row n'est pas packed, stepb>stepa
     546  else if(stepa!=1 && stepb!=1 && stepb>stepa) {
     547    //cout<<"A.col not packed && B.row not packed ==> optimize on B "<<stepa<<" "<<stepb<<endl;
     548    const T * pea;
     549    T * peb = new T[rm.NCols()];
     550    for(c=0; c<rm.NCols(); c++) {     // Boucle sur les colonnes de B
     551      pe = &(b(0,c));
     552      for(k=0; k<NCols(); k++) {peb[k] = *pe; pe+=stepb;}
     553      for(r=0; r<rm.NRows(); r++) {     // Boucle sur les lignes de A
     554        sum = 0;
     555        pea = &((*this)(r,0));
     556        for(k=0; k<NCols(); k++) {sum += (*pea)*peb[k]; pea+=stepa;}
     557        rm(r,c) = sum;
     558      }
     559    }
     560    delete [] peb;
     561  }
     562  // A.col n'est pas packed  et  B.row n'est pas packed, stepa>=stepb
     563  else if(stepa!=1 && stepb!=1) {
     564    //cout<<"A.col not packed && B.row not packed ==> optimize on A "<<stepa<<" "<<stepb<<endl;
     565    T * pea = new T[rm.NCols()];
     566    const T * peb;
     567    for(r=0; r<rm.NRows(); r++) {     // Boucle sur les lignes de A
     568      pe = &((*this)(r,0));
     569      for(k=0; k<NCols(); k++) {pea[k] = *pe; pe+=stepa;}
     570      for(c=0; c<rm.NCols(); c++) {     // Boucle sur les colonnes de B
     571        sum = 0;
     572        peb = &(b(0,c));
     573        for(k=0; k<NCols(); k++) {sum += pea[k]*(*peb); peb+=stepb;}
     574        rm(r,c) = sum;
     575      }
     576    }
     577    delete [] pea;
     578  }
     579  else {
     580    cout<<"TMatrix<T>::Multiply(b) Optimize case not treated... Please report BUG !!! "<<endl;
     581    throw(SzMismatchError("TMatrix<T>::Multiply(b) Optimize case not treated... Please report BUG !!! ") );
     582  }
     583
     584  return rm;
     585}
    439586
    440587///////////////////////////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.