Thanks for the update, Matthew. I am currently getting Version 4.0 of the Science Collection ready to release in the next few weeks. It will require PLT Scheme 4.2.3 or later. As I said earlier, I am using unsafe operations extensively in the implementation of the Chebyshev approximation routines (used to implement many of the special functions), the ordinary differential equation (ODE) solvers (also used by the Simulation Collection for continuous models), and the statistics routines.<br>
<br>I am attempting to ensure that even when using the unchecked versions of the routines (that bypass the contract checks) there are no instances where the routines crash. Basically, I have a couple of macros that I used to ensure reals are floats and integers are fixnums before using the unsafe operations and raise an exception if they cannot be coerced. There is obviously some overhead in doing this, but in most cases I think it is unschemely to require floats for all reals input to the routines. [There aren't that many occasions where I use unsafe fixnums except in cases where I know they are vector indices.] This isn't a problem with the Chebyshev and ODE solvers where I control the internal state and can make sure that all of the state variables are indeed floats.<br>
<br>I guess the point of this message is to say I will use the unsafe operations to implement (some of) the computationally intensive procedures, but attempt to ensure that the resulting routines are not themselves 'unsafe' (in the sense of crashing when given 'bad' data).<br>
<br>I can make the routines available for testing by interested parties prior to releasing them to PLaneT. This would also allow you to critique the unsafe constructs and see if you have any suggestions for improving my use of them.<br>
<br>Doug<br><br><div class="gmail_quote">On Sun, Dec 13, 2009 at 11:46 AM, Matthew Flatt <span dir="ltr"><<a href="mailto:mflatt@cs.utah.edu">mflatt@cs.utah.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
At Fri, 4 Dec 2009 17:49:45 -0700, Doug Williams wrote:<br>
> I have updated several of the more computationally expensive components of<br>
> the science collection [...] to use the new unsafe operations. [...]<br>
><br>
> The question is to what extent you guys as the development team still<br>
> consider these as experimental features.<br>
<br>
We previously defined "experimental" as<br>
<br>
I think of it as an experiment in that I'm not sure that this is the<br>
right approach for better performance. But it seems worth a try, and<br>
if it works well for many purposes, then it'll stick.<br>
<br>
It sounds like the unchecked--unsafe operations are working for you, we<br>
have found other uses in parallel algorithms, and they seem to be<br>
working out in general. So, it's going to stick.<br>
<br>
<br>
As of yesterday, the bytecode compiler can now improve the chances for<br>
unboxed flonums in the JIT. For example, the bytecode compiler<br>
effectively converts<br>
<br>
(let ([y (unsafe-fl+ c d)]<br>
[x (unsafe-fl+ a b)])<br>
(unsafe-fl+ x (unsafe-fl+ y (unsafe-fx->fl (+ q v)))))<br>
<br>
to<br>
<br>
(let ([q+v (+ q v)])<br>
(unsafe-fl+ (unsafe-fl+ a b)<br>
(unsafe-fl+ (unsafe-fl+ c d)<br>
(unsafe-fx->fl q+v))<br>
<br>
so that all the JIT sees all the `unsafe-fl' operations together.<br>
<br>
The bytecode compiler can push `let'-bound flonum-producing expressions<br>
into other flonum operations only when the corresponding binding is<br>
used just once. Also, the compiler must be able to tell that the move<br>
doesn't reorder the expression relative to an observable effect. For<br>
example, if you insert a `printf' before the body the of `let' above,<br>
then the `let' bindings are not moved down. I might improve the<br>
transformation to consider specific dependencies, instead of giving up<br>
on all observable effects (e.g., `printf' definitely won't affect the<br>
values of `a' through `d' if none of them are mutable). Already,<br>
though, a potential crash from an unsafe operation, doesn't count for<br>
moving other expressions; for example, the right-hand sides of the `y'<br>
and `x' bindings are reordered above, on the grounds that you cannot<br>
reliably detect an crashes that might happen as a side effect.<br>
<br>
The transformation to pull non-flonum expressions out of an `unsafe-fl'<br>
argument position is less constrained. Multiple arguments always can be<br>
lifted to fresh `let' bindings without changing the order of the<br>
expressions. And since potential crashes from unsafe operations don't<br>
count, nested unsafe operations can be kept as immediate arguments<br>
without concern for argument order.<br>
<br>
Two main weaknesses remain:<br>
<br>
* It's not so easy to tell when the compiler will be able to avoid<br>
boxing. The `mzc --decompile' tool now adds `#%flonum' annotations<br>
on decompiled code to help you double-check, but that's not a great<br>
help when writing programs in the first place.<br>
<br>
* Flonum results that are used more than once (such as a `let' binding<br>
of an identifier that is used in two places) are not yet handled by<br>
the JIT. Adding some form of stack-based local storage, instead of<br>
always boxing in the heap, is the next step. That change will also<br>
simplify the rules about when intermediate flonums are unboxed.<br>
<br>
</blockquote></div><br>