Alan,

> Hi Loup
> Actually, your last guess was how we thought most of the optimizations would
> be done (as separate code "guarded" by the meanings). For example, one idea
> was that Cairo could be the optimizations of the "graphics meanings code" we
> would come up with. But Dan Amelang did such a great job at the meanings that
> they ran fast enough tempt us to use them directly (rather than on a 
> supercomputer,
> etc.). In practice, the optimizations we did do are done in the translation 
> chain and
> in the run-time, and Cairo never entered the picture.
> 
> However, this is a great area for developing more technique for how "math" can
> be made practical -- because the model is so "pretty" and "compact" -- and 
> there
> is much more that could be done here.

Here is an old idea I had for a "cache manager" (as described in
http://www.merlintec.com/lsi/tech.html):

One feature that distinguishes programs by experts from those of novices
is the use of caching as a performance enhancement. Saving results for
later reuse greatly decreases source code readability, unfortunately,
obscuring program logic and making debugging much harder. Reflection
allows us to move caching to a separate implementation layer in a cache
manager object. So the application can be written and debugged "naively"
and, after it works, can be annotated to use the cache manager at
critical points to significantly improve performance without having to
write a new version.

This is only possible because Merlin uses message passing "at the
bottom" and includes a reflective access to such a fundamental
operation. In other words, user applications are never made up of mainly
"big black boxes" which the OS can do nothing about. Even simple math
expressions as '(x * 2 ) + y' are entirely built from messages that are
(in theory - the compiler actually eliminates most of the overhead)
handled by a set of meta-objects. So all that the system has to do when
the user annotates an expression as cacheable is to replace the standard
send meta-object with one that looks up its arguments in a table (cache)
and returns a previously calculated answer if it is found there.
Otherwise it works exactly like a normal send meta-object.

An example of how this works is in rendering text. A given font's glyphs
might be given as sets of control points for Bezier curves describing
their outlines plus some "hints" for adjusting these points when
scaling. We could then draw a character from a font called myFont on
aCanvas with the expression:

   aCanvas drawPixmap: ((myFont glyphFor: 'a' Size: 12)

                                asVectors asPixmap)

This should work perfectly, but will be unacceptably slow. For each time
some character must be shown in the display its points must be scaled by
the 'glyphFor:Size:' method, then the control points must be rendered as
short vectors approximating the indicated Bezier curves ('asVectors')
and finally these vectors must be used to fill in a picture ('asPixmap')
which can finally simply be blasted on the screen for the final result.
By marking each of these messages as cacheable, the next time
'glyphFor:Size:' is sent to myFont with exactly 'a' and 12 as arguments
it will return the same list of control points without executing the
method again. Sending a cacheable 'asVectors' message to the same list
of point as before will fetch the same list of vectors as was created
the first time, and sending 'asPixmap' to that results in the same
character image without actually invoking the filling method once more.
So we have replaced three very complex and slow calculations with three
simple table lookups. If you think that even that is too much, you are
right. The cached control point lists and short vector lists are not
really needed. Unfortunately, the cache manager can do nothing about
that, but if the user moves multiply cached expression to their own
methods like this:

  pixmapForFont: f Char: c Size: s =  ( (f glyphFor: c Size: s)

                                          asVectors asPixmap).

   ....

   aCanvas drawPixmap: (pixmapForFont: myFont Char: 'a' Size: 12)

Now we can make only the 'pixmapForFont:Char:Size:' method cacheable if
we want. This will save the final pixmaps without also storing the
intermediate (and useless to us) results. This did involve rewriting
application code, but actually made it a little more readable, unlike
when caching is "hand coded".

> Why can't a Nile backend for the GPU board be written? Did I miss something?

As Reuben Thomas pointed it, the needed information is not available. In
fact, there was no information at all about the chip until this week,
but now we have some 30% (the most important part for porting the basic
funcionality of some OS). This is the same issue that the OLPC people
had (worse in their case, because people would promise to release the
information to get them to use a chip and then just didn't do it). Even
dealing with FPGA is a pain because of the secret parts.

-- Jecel

_______________________________________________
fonc mailing list
[email protected]
http://vpri.org/mailman/listinfo/fonc

Reply via email to