[Haskell-cafe] idea for avoiding temporaries
Claus Reinke
claus.reinke at talk21.com
Sun Mar 11 15:03:59 EDT 2007
> * The algorithm as written already tries to express minimal storage.
> The only question is, do +=, -=, and := update their left-hand side
> in place, or do we think of them (in the Haskell model of the
> universe) as fresh arrays, and the previous values as newly-created
> garbage? My challenge to fellow Haskell hackers: find a way to
> express this such that it doesn't look so imperative.
>
> * Even if we do a good job with += and -=, which is what David seems
> to be looking for, we still have those irritating := assignments---
> we'd like to throw out the old p and reuse the space in the last
> line. And we'd like to have one piece of storage to hold the q on
> each successive iteration. So even if we solve David's problem, we
> still haven't matched the space requirements of the imperative code.
i find it difficult to discuss performance issues without concrete code examples,
so i decided to convert Jan-Willem's loop code into Haskell. at first, i just naively
translated the loop to recursion over lists, then i tried to produce an update-inplace
variant based on some form of arrays, and finally i added a variant based on strict
lists (would be nice to have standard libraries for (head-/spine-)strict lists, btw).
both the array and strict list versions avoid some intermediate structures; for the
arbitrarily invented, relatively small inputs i've tried, strict lists are the clear winner,
thanks to lower memory traffic, but i'd like some feedback from the experts:
-are there any obvious inefficiencies in the array code?
-what does your real code look like, in view of scaling to much larger inputs?
-i tried to keep the computations equal, but seem to have introduced a
small variance in the strict list version, which i can't seem to spot by
staring at it. any ideas?
-i assume the memory overhead of binary strict lists is unacceptable for
large inputs, but i'm still waiting for those polymorphic bytestrings..;-)
while playing with this code, it occurred to me that situations as that described by
David (small numbers of huge structures of constant size, with no nested pointers)
are less suited for compacting garbage collection than for slot-reusing reference
counting. GC wins in the common situation of many variable-sized, frequently
created/destroyed structures, by touching only those objects that are live when
space runs out, while RC has a higher continuous overhead.
as i mentioned earlier, i'm not sure whether update-in-place vs recreate is so
bad for whole-array updates, but the real win could be not having to copy the
huge live arrays arround at GC time (either from old to new space, or within
one space, to create contiguous free slots while compacting the occupied slots).
so instead of update-in-place in virtual memory space, which will still be copied
at GC time, one would want to pin the virtual region in which the arrays are
allocated to a real memory region, and tell the GC to keep its hands off it (none
of that space will be released until the loop ends, all of it will be released after
the loop ends and a copy of z has been made). does this make sense to the
number crunchers and memory managers out there? and is there a way to
allocate Haskell arrays to such pinned memory regions?
claus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CG.hs
Type: application/octet-stream
Size: 5796 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070311/74e5b3b8/CG.obj
More information about the Haskell-Cafe
mailing list