[racket] Everything type-checks; on to benchmarking and optimization
At Fri, 28 Feb 2014 10:50:11 -0500,
Stephen Bloch wrote:
>
> On Feb 28, 2014, at 10:34 AM, Vincent St-Amour <stamourv at ccs.neu.edu> wrote:
>
> > This code is probably the problem:
> >
> > (require/typed racket/unsafe/ops
> > [(unsafe-fx+ index+) [Index Index -> Index]]
> > [unsafe-fx+ [Fixnum Fixnum -> Fixnum]]
> > [unsafe-fx- (Fixnum Fixnum -> Fixnum)]
> > [unsafe-fl+ (Flonum Flonum -> Flonum)]
> > [unsafe-fl- (Flonum Flonum -> Flonum)]
> > [unsafe-fl* (Flonum Flonum -> Flonum)]
> > )
> >
> > TR already provides types for these functions, so you can use:
> >
> > (require racket/unsafe/ops)
> >
> > `require/typed' adds contracts to its imports (for safe typed-untyped
> > interop), which add a significant cost (85% of the running time,
> > according to the contract profiler).
>
> Yike! Thanks; I never would have thought of that.
>
> There’s probably something in the documentation about “require/typed”
> as a source of inefficiency, but for whatever reason I didn’t stumble
> upon it.
The "typed-untyped interaction" section of the TR guide does mention the
overhead of contracts. I'll add mentions elsewhere in the docs (probably
in the caveats and optimization sections).
> > Removing the `require/typed' (except for `index+') brings the running
> > time (of the portion you were profiling) down from 22s to 15s. Replacing
> > the `index+'s with generic `+' and `assert's (to enforce `Index'
> > results) brings the running time down to 2.5s.
>
> Generic ‘+’, not ‘unsafe-fx+’?
In this case, Typed Racket optimized it automatically based on the type
information, as confirmed by optimization coach.
> Should I be using racket/unsafe/ops at all?
I would recommend first seeing whether TR already optimizes operations
for you. If it doesn't, you can try adjusting the types. If that doesn't
work, then unsafe operations are a good option. I tend to use them as a
last resort.
Unsafe fixnum operations, specifically, are not usually a significant
improvement over generic arithmetic, because the fixnum case is already
on the fast path of generic operations, and fixnums are not boxed
(unlike flonums).
Vincent