Ticket #51 (new enhancement)

Opened 2 years ago

Last modified 21 months ago

optimization of fst . unzip . zip

Reported by: choener Owned by:
Priority: major Milestone:
Version: 0.7 Keywords: code-path optimization
Cc: choener@…

Description

Hi,

lets assume this:

f n = map (\(a,b) -> (a+1,b+1)) . zip (enumFromN 0 n) (enumFromN 0 n)
g = fst . unzip

main = print . sum . g . f $ 100

In this case i would like to have sum . g . f reduce to sum . enumFromN 0 but this does not happen. Is it in any way possible to get the optimizer to "cut out" unused code paths? The map operation in "f n" is basically a placeholder for something complicated.

If this is possible to optimize correctly, it becomes possible to nicely describe some complicated code paths.

Change History

Changed 2 years ago by rl

  • milestone set to 0.8

We have some support for this in DPH but I haven't included it in vector yet. Note that for fusion to work, you would have to write this:

g = map fst

rather than this:

g = fst . unzip

The latter is impossible to match on. For the former, we're just missing a couple of rules, I'll add them in the next release.

Changed 2 years ago by choener

I have no problem writing "map fst" if that enables said optimizations in the next release. It means that I can write a number of things in a very "nice" way.

Thanks, Christian

Changed 2 years ago by rl

This won't make it into 0.7.1 because I don't want to break DPH with this release. I'll try to release 0.8 soon(ish) after and that should contain the necessary fusion magic (unless there is some unforeseen problem with it).

Changed 2 years ago by rl

  • priority changed from minor to major

Changed 21 months ago by rl

  • milestone 0.8 deleted

It turns out that implementing this particular bit of fusion is an utter pain. I might have a better idea. If you could create a lazy pair of two strict vectors and treat that pair itself as a vector, would that solve the problem? So something like this (yes, the kinds don't quite work out):

data family Tuple v a
data instance Tuple (va,vb) (a,b) = Tuple2 (va a) (vb b)
instance (Vector va a, Vector vb b) => Vector (Tuple (va,vb)) (a,b) where
  ...

The ticket for this is #58.

Changed 21 months ago by choener

Currently, what is going on is always:

g i z = map (\k -> (k, work k)) $ enumFromN i z

That is a generator produces indices 'k' which are paired with a function doing work. In the forward phase, we are only interested in the work:

reduce i z = fold reducer neutral $ g i z

In the backtrace, we need the index as well -- but do not care about performance:

xs <- toList $ g i z

I'll upload a number of libraries in the coming days. Once done I'll hope to have some time to optimize those.

Note: See TracTickets for help on using tickets.