Efficient UArray dot-product?

Mike Gunter m@ryangunter.com
Sun, 02 Jun 2002 14:46:00 -0700


Is it possible to write an dot-product function that GHC will compile
to efficient code without using unsafeAt?  I've tried and can't.  I'm
looking at generic IArray functions pragma-specialized to UArray Int
Double.  With unsafeAt the -ddump-simpl output looks optimal to me
(aside from not unrolling or pipelining**):

  loop i s | i > ubSI = s
           | otherwise = let s' = s + (small `unsafeAt` i) * (big `unsafeAt` (off + i))
                         in seq s' $ loop (i + 1) s'

compiles to

   $wloop
            = \ ww12 L :: PrelGHC.Int# ww13 L :: PrelGHC.Double# ->
                case PrelGHC.># ww12 ww9 of wild3 L {
                  PrelBase.True -> PrelFloat.$wD# ww13;
                  PrelBase.False ->
                $wloop
                  (PrelGHC.+# ww12 1)
                  (PrelGHC.+##
                     ww13
                     (PrelGHC.*##
                    (PrelGHC.indexDoubleArray# ww2 ww12)
                    (PrelGHC.indexDoubleArray# ww6 (PrelGHC.+# a2 ww12))))
                };
            } in 


Without it (i.e. with (!)) the compiler will only use primitive
arithmetic for addressing one of the arrays.  Why?

Is there a way to write dot-product that produces good code without
resorting to unsafeAt?

    thanks,
    mike


** Pipelining probably isn't going to be worth your time in so far as
   you're targeting processors with dynamic scheduling.  They'll
   pipeline things for you.