Open arekfu opened 8 years ago
I also would like to know this. Unfortunately my Haskell performance measurement knowledge isn't there to know how to find out.
The GHC documentation (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#unpack-pragma) says that the UNPACK
machinery can see through newtypes, but I'm not sure whether it can see through the type synonyms and associated data family to realize that Length Double
=> Quantity DLength Double
=> Dimensional DQuantity DLength Double
is ultimately a newtype, and again I don't know how to find out.
Is this an area you have experience with? If you'd be willing to contribute, it seems like we definitely could use better benchmarks and documentation of their results.
One way could be to write some benchmarks (using criterion?) where we perform the equivalent calculations using dimensional and using straight Double
s and compare the timing.
The original (2006-ish) idea was that with the newtypes
instead of data
all the type information would get removed at compile time and all that would be left would be arithmetic on Double
s (or whatever the underlying data type was). I never did benchmark as far as I can recall, nor am I sure to what extent this idea is valid with the current feature set. It may also never have been true when you get to functors and such.
Definitely this is what we need to do, I'm just not clear on how to do it. In particular I don't know how to write it so that it measures the performance of the arithmetic ignoring the performance of constructing the Quantity
s in the first place, just to separate concerns. (Because *~ meter
requires a multiplication by 1, we could try to get really clever in *~~
and skip it but I'd like to have performance measurements justifying it.)
Even in the new design with named units, Quantity
is still a newtype
. (+) :: Quantity d a -> Quantity d a -> Quantity d a
is defined to be (+) = liftQ2 (Prelude.+) = coerce (Prelude.+)
, so I would expect that we should have similar performance, but again I don't know how to measure it.
Multiplication and division is a different story, since we have overloaded versions that also operate on Unit
s and thus do a bunch of rigamarole. If we had benchmarks to justify and test it, we might benefit from some sort of RULES
pragma specializing (*)
at type Quantity d1 a -> Quantity d2 a -> Quantity d3 a
to a similar implementation, but again I don't know how to write it.
I don't know what I'm doing wrong, but it's obviously at least one thing because it says that the wrapped version is 5x faster.
Anybody see what's going on? https://github.com/dmcclean/dimensional/blob/improved-benchmarks/benchmarks/Main.hs
Strange indeed. Try these and note the difference between RawSum1
and RawSum2
:
[ bench "Sum1" $ nf sum xs
, bench "Sum2" $ nf (P.sum . (/~~ siUnit)) xs
, bench "RawSum1" $ nf P.sum xs'
, bench "RawSum2" $ nf (P.sum . id) xs'
, bench "RawSum3" $ nf (foldr (P.+) 0) xs'
]
(By the way, it seems the force
in setupEnv
is doing nothing.)
inspection-testing
may also be an approach here, for things that are supposed to be zero-cost.
How much overhead does
dimensional
introduce? I understand that unit homogeneity is statically checked, but is there an overhead for unit manipulation (arithmetics, etc.)? Is it possible to unbox ({-# UNPACK #-}
) dimensionful quantities in data structures where the corresponding dimensionless quantity would be unboxable? It would be nice to have a sentence or two in the README file.