Lazy computation being repeated?

Tyson Whitehead twhitehead at gmail.com
Wed May 27 19:07:53 EDT 2009


I have a program that seems to me to be exhibiting strange behaviour.  
Basically, it looks like something somewhere is not being updated, and this is 
resulting in (very expensive) computation being repeated.

The program in question goes like so.  The results from the expensive 
calculation are stored in this structure

 data Cache = Cache { cacheBits0 :: UArr Float,
                      cacheBits1 :: UArr Float }

and computed by this function (which takes several gigs of RAM)

 cacheIndex :: ... -> Cache
 cacheIndex ... = ...

The main program is

  main = catch prog error
      where prog = do ...
                      let !cache = cacheIndex ...
                      ...
                      run cache ...
            ...

The run function reads an input line from stdin and calls effectChange to 
performs the indicated calculation

  run cache ... = loop
      where loop = do ...
                      case effectChange ... cache of
                        ...
                      ...
                      loop

The effectChange function is calculates the change in an auto correlation.  It 
is made much cheaper (order too fast to notice) through the use of a the one 
time computations stored in cacheBits0 and cacheBits1 (order several seconds).

Whether cacheBits1 is used or not depends on the input, while cacheBits0 is 
always used because I used lengthU cacheBits0 [the fast one from UArr] to get 
the length of both of them.  The first line of input causes a several second 
delay and lots of memory to be allocated (the cacheBits are being computed).

Repeated lines of input respond very quickly and the memory stays mostly 
constant, unless cacheBits1 is used, in which case there is always a delay of 
several seconds and big jumps in memory allocation.

The only thing I can think of that each time effectsChange is being run and it 
is uses cacheBits1, it causes it value to be recomputed.  Indeed, the delay 
and big memory jumps go away if I change all references of cacheBits1 to 
cacheBits0 in effectsChange or make the data fields strict like so

 data Cache = Cache { cacheBits0 :: !(UArr Float),
                      cacheBits1 :: !(UArr Float) }

Does this make sense?  Am I missing some reason why this should be the 
expected behaviour for this program?

Thanks!  -Tyson


More information about the Glasgow-haskell-users mailing list