[racket] Optimization; converting 'Float' to 'Fixnum' in Typed Racket

From: Vincent St-Amour (stamourv at ccs.neu.edu)
Date: Sat Feb 18 23:04:33 EST 2012

At Sat, 18 Feb 2012 21:07:05 -0500,
SF wrote:
> I'm trying to optimize some code that processes a bunch of data,
> basically image pixels, which currently takes on the order of several
> seconds and seems like it should be much faster (important because
> it's an interactive application). Coming from C++ I have a good idea
> in my mind of how I'd write it with low-level operations. I read up on
> Racket optimization. It is still somewhat unclear to me how Racket
> deals with fixnums, flonums, unsafe operations, Typed Racket types,
> and how it all fits together.

Racket's unsafe operations do not perform any checks and guide the
compiler's unboxing optimizations. Using them can lead to significant
speedups.

Typed Racket performs type-driven optimization when it can guarantee
that doing so is safe. Most of its optimizations replace generic
arithmetic with specialized unsafe operations. The performance
benefits are equivalent to using unsafe operations manually. The
advantage of using TR is that it won't introduce bugs by optimizing
when it's not safe to do so.

In practice, TR will optimize pretty much any floating-point
computation. In the case of fixnum operations, it optimizes only when
it can guarantee that no overflow will happen. This means that you may
need to help it a bit if you want to get fixnum optimizations.

To see how TR optimizes your code (for example, to make sure that you
get all the optimizations you want), check out the "performance
report" DrRacket tool.

> I chose to optimize my program (partly
> to learn how) incrementally, trying all the options, timing at every
> step with debugging info turned off. This worked until I wanted to
> convert Integers to Fixnums in Typed Racket (which has been giving me
> much faster results than anything in untyped Racket).

You don't need to convert between integers and fixnums. Fixnums are
simply integers that are small enough to be represented as tagged
machine integers. If an operation on fixnums would cause an overflow,
the result is transparently promoted to a bignum instead.

To use fixnums in TR, you can annotate your variables as being of
`Fixnum' type. However, due to the promotion semantics, fixnums have
pretty bad closure properties, which means that the result of, say,
adding two fixnums is not guaranteed to be a fixnum itself and has to
be given the `Integer' type.

To help with this, TR provides an `Index' type which is for integers
bounded by the length of the longest possible vector (smaller than a
fixnum). Adding two of these is guaranteed to produce a `Fixnum'.

The bottom line is that it's possible to get fixnum optimizations in
TR, but since TR has to be conservative in order to be safe, sometimes
you may have to use unsafe fixnum operations manually to get the
performance you want.

> The problem is that I can't find a way to convert a Float to a Fixnum,
> only to an Integer. None of fl->fx, unsafe-fl->fx, or
> fl->exact-integer work, as Type Checker tells me they're untyped
> identifiers.

That should work. I'll look into that.

Vincent

Posted on the users mailing list.