[racket] Perlin and simplex noise - optimizing Racket code

From: JP Verkamp (racket at jverkamp.com)
Date: Thu Apr 11 20:14:48 EDT 2013

Thanks for the advice! It's certainly been an interesting journey into
Typed Racket... :)

Here are the results thus far (for a 256x256 perlin, simplex, and
colored-simplex image).

Original:
  cpu time: 1139 real time: 1134 gc time: 232
  cpu time: 780 real time: 773 gc time: 124
  cpu time: 1950 real time: 2044 gc time: 328

Typed:
  cpu time: 640 real time: 653 gc time: 110
  cpu time: 546 real time: 542 gc time: 62
  cpu time: 1342 real time: 1364 gc time: 218

So it's definitely a good start.

Unfortunately, there are a few oddities that I'm not sure how to deal with.

*1) *Which is more idiomatic / easier for Typed Racket to deal with:

(: mix (Flonum Flonum Flonum -> Flonum))
(define (mix a b t)
  ...)

(define: (mix [a : Flonum] [b : Flonum] [t : Flonum]) : Flonum
  ...)

Right now, I'm using the former, but I'm not sure I'm happy with it.

*2)* How can I deal with integer values (specifically 0) to a function with
flonum types?

Specifically, perlin (and simplex) have the type:\

(: perlin
   (case-> (Flonum -> Flonum)
           (Flonum Flonum -> Flonum)
           (Flonum Flonum Flonum -> Flonum)))

But if I try to do something like this:

(perlin (* 1.0 (/ 0 256)))

I get this error:

Type Checker: No function domains matched in function application:
Domains: Flonum Flonum Flonum
         Flonum Flonum
         Flonum
Arguments: Zero

Basically, (* 1.0 (/ 0 256)) is 0, not 0.0. For the timing tests above, I
worked around this with real->double-flonum but that seems suboptimal (they
types are leaking). Is there something I'm missing there?

*3)* How do I type a color% / bitmap%?

I tried typing noisy-image-test.rkt, but I kept running into this. I can
use Any, but it seems like objects should be typeable. No luck finding out
how though.

I'll keep hacking at it, but that's what I have for the moment.

JP


On Thu, Apr 11, 2013 at 3:54 PM, Vincent St-Amour <stamourv at ccs.neu.edu>wrote:

> At Thu, 11 Apr 2013 13:07:27 -0400,
> JP Verkamp wrote:
> >
> > [1  <multipart/alternative (7bit)>]
> > [1.1  <text/plain; UTF-8 (7bit)>]
> > Partially out of curiosity and partially in my ongoing quest to try out
> > game development in Racket, I've implemented a pure Racket version each
> for
> > Perlin and simplex noise. It's pretty much a direct translation of the
> code
> > from this PDF, originally in C:
> > http://webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
> >
> > Here is a blog post with some pretty pictures but little actual code:
> > http://blog.jverkamp.com/2013/04/11/perlin-and-simplex-noise-in-racket/
> >
> > Here's just the code:
> > https://github.com/jpverkamp/noise
> >
> > It's definitely not pure / functional, but I think it's relatively easy
> to
> > read (or as easy as noise functions can be).
> >
> > What I'm wondering though is if someone with a bit more experience in
> > optimizing Racket code could take a look at it. I know that it should be
> > possible to get a bit more speed; it's almost all number crunching,
> mostly
> > floating point math but with a few integer only bits (those are causing
> the
> > most trouble...). At the moment, I can think of at least three routes for
> > optimization although I'm probably missing something:
> >
> > - using (racket/floum) -- I've tried just blindly replacing * + - / with
> > fl* fl+ fl- fl/ (and fixing the numerous errors that crop up), but it
> > doesn't seem to result in much of a speedup at all. I think that this is
> a
> > combination of still requiring runtime checks on the values and having to
> > convert between exact/inexact, but I'm not sure.
> >
> > - using Typed Racket -- Theoretically this will allow the compiler to
> > choose the correct functions as above and avoid having to do any runtime
> > checks at all, although I'm not sure how much of that has been
> implemented.
>
> I had a quick look at your code, and I think Typed Racket should be able
> to help. The TR optimizer can specialize numeric operations, which
> removes runtime checks and allows the Racket compiler to unbox
> intermediate results.
>
> To get the most of the TR optimizer, you can try the Optimization Coach
> DrRacket plugin. It reports the specializations that TR is doing and
> points out specialization opportunities that would require code/type
> changes to be safe.
>
> Vincent
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130411/85841885/attachment.html>

Posted on the users mailing list.