Re: Matrix multiplication performance

palik imre <[email protected]>
Newsgroups gmane.comp.lib.boost.ublas
Message-ID <[email protected]>
Extending the same idea for complex multiplication:

template <typename Index, typename T, typename TC>
typename std::enable_if<std::is_floating_point<T>::value,
         void>::type
ugemm(Index kc, std::complex<TC> alpha,
           const T *Ar, const T *Ai, const T *Br, const T *Bi,
      std::complex<TC> beta,
      std::complex<TC> *C, Index incRowC, Index incColC)
{
    static const Index MR = BlockSize<T>::MR;
    static const Index NR = BlockSize<T>::NR;
    static const unsigned div = 32/sizeof(T);
    typedef T vx __attribute__((vector_size (32)));

    vx Pr[MR*NR/div] __attribute__ ((aligned (128))) = {};
    vx Pi[MR*NR/div] __attribute__ ((aligned (128))) = {};
    const vx *Br_ = (vx *)Br;
    const vx *Bi_ = (vx *)Bi;
    for (Index l=0; l<kc; ++l) {
      for (Index j=0; j<(NR/div); ++j) {
        for (Index i=0; i<MR; ++i) {
          Pr[i * NR/div + j] += Ar[i + l * MR]*Br_[l*(NR/div)+j] - Ai[i + l * MR]*Bi_[l*(NR/div)+j];
          Pi[i * NR/div + j] += Ar[i + l * MR]*Bi_[l*(NR/div)+j] + Ai[i + l * MR]*Br_[l*(NR/div)+j];
        }
      }
    }

    T *Pr_ = (T *)Pr;
    T *Pi_ = (T *)Pi;
    for (Index i=0; i<MR; ++i) {
      for (Index j=0; j<NR; ++j) {
        C[i*incRowC+j*incColC] *= beta;
        C[i*incRowC+j*incColC] += alpha* std::complex<TC>(Pr_[i * NR + j], Pi_[i * NR + j]);
      }
    }
}


Cheers,

Imre


--------------------------------------------
On Fri, 29/1/16, palik imre <[email protected]> wrote:

 Subject: Re: [ublas] Matrix multiplication performance
 To: "palik imre" <[email protected]>, "Michael Lehn" <[email protected]>, "ublas mailing list" <[email protected]>, "ublas mailing list" <[email protected]>
 Date: Friday, 29 January, 2016, 23:31
 
 Here is a more sane
 kernel using gcc simd vectors:
 
 template <typename Index, typename T>
 typename
 std::enable_if<std::is_floating_point<T>::value,
          void>::type
 ugemm(Index kc, T alpha,
    
        const T *A, const T *B,
            T beta,
            T *C, Index incRowC,
 Index incColC)
 {
    
 static const Index MR = BlockSize<T>::MR;
     static const Index NR =
 BlockSize<T>::NR;
     static const
 unsigned div = 32/sizeof(T);
     typedef T
 vx __attribute__((vector_size (32)));
 
     vx P[MR*NR/div] __attribute__ ((aligned
 (128))) = {};
     const vx *B_ = (vx
 *)B;
     for (Index l=0; l<kc; ++l)
 {
       for (Index j=0; j<(NR/div);
 ++j) {
         for (Index i=0; i<MR;
 ++i) {
           P[i * NR/div + j] +=
 A[i + l * MR]*B_[l*(NR/div)+j];
        
 }
       }
     }
 
     T *P_ = (T *)P;
     for (Index i=0; i<MR; ++i) {
       for (Index j=0; j<NR; ++j) {
         C[i*incRowC+j*incColC] *= beta;
         C[i*incRowC+j*incColC] +=
 alpha*P_[i * NR + j];
       }
     }
 }
 
 
 this plugs nicely to
 Michael's code, and slightly faster than my previous try
 (but still nowhere near to Michael's hand crafted
 kernel).
 
 The good blocksize
 for double is MR=2, NR=16, KC=512
 multiply
 MR and NR by 2 for float.
 
 
 Cheers,
 
 Imre
_______________________________________________
ublas mailing list
[email protected]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.