laziness, memoization and inlining

Don Stewart dons at galois.com
Tue May 13 23:20:11 EDT 2008


sedillard:
> Hi Everybody,
> 
> I'm experiencing some undesirable performance behavior, I suspect from
> inlining things that shouldn't be, defeating my memoization attempts.
> I've been experimenting with purely functional 3D modeling code, so a
> mesh is (initially) something like
> 
> > type Mesh = Map (Int,Int) (Int,Int)
> 
> that is, a function from from an edge to the next edge around the
> face, where an edge is a pair of Ints (the vertices.)
> 
> This nice and pure and everything, but its slow to read from. So I
> have another immutable pointer-based representation
> 
> > data Edge = Edge { edgeOrg :: Int , edgeSym :: Edge , edgeNext :: Edge }
> 
> which is something like a half-edge, for those familiar with such
> things. Its basically a big net made of circular lists that are tied
> together. I do the knot tying stuff to create this thing,
> 
> > memoMesh :: Map (Int,Int) (Int,Int) -> Edge Int
> > memoMesh nexts = head $ Map.elems ties
> >   where
> >     ties = Map.mapWithKey (\ij _ -> make ij) nexts
> >     lookup ij = trace "hello" $ fromJust $ Map.lookup ij ties
> >     make ij@(i,j) = Edge i (lookup (j,i)) (lookup . fromJust $ Map.lookup ij nexts)
> 
> The program first loads the model file and creates the Edge-based mesh
> using the memoMesh function. The result is then captured in the
> closure for the rendering callback in GLUT. When I compile with -O0 I
> see the "hello" traces only during the first drawing. Subsequent
> redraws are fast and output no traces. When I compile with -O1 or -O2,
> the traces get output on every redraw, and its very slow. I suspect
> all of the calls which create the mesh are inlined into the rendering
> callback, effectively rebuilding the mesh on every draw.

Hmm. I wonder if *this* is the no-state-hack at play.

Does -fno-state-hack help?

> I've tried littering NOINLINE pragmas all around, to no avail.
> 
> The main function is something like
> 
> > main = do
> >   initGlut ...
> >   rawMesh <- loadMeshFile ...
> >   let
> >     mesh = memoMesh rawMesh
> >     otherstuff = ...
> >     display =
> >       draw mesh >> amongOtherThings
> >   displayCallback $= display
> >   glutMainLoop
> 
> Can someone help me understand what's going on here? Is there a nice
> solution to this, hopefully a single strategic pragma or something?

Is it possible to boil this down to a program that doesn't use GL?

-- Don


More information about the Glasgow-haskell-users mailing list