anyone using single-flonums?

181 views
Skip to first unread message

Matthew Flatt

unread,
May 29, 2019, 11:52:43 AM5/29/19
to Racket Users
Does anyone use single-flonums in Racket?

I don't mean `_float` or `f32vector`s, which convert C `float`s or
32-bit array elements into regular double-precision Racket flonums. I
mean literals like `3.0f0` or functions like `real->single-flonum`,
which produce a Racket number that uses only 32 bits for arithmetic.

Chez Scheme doesn't support single-precision floating-point numbers,
and adding them would be a lot of work --- for no benefit, if it turns
out that no one is using those kinds of numbers.

My guess is that no one uses them currently, because it's rare that
you'd want to trade speed for *im*precision. Single-flonums in Racket
are significantly slower than regular flonums, because they're not
treated as a common case. The only use I can think of, and the one that
inspired the original experiment, is to try to faithfully replicate a C
`float` calculation in Racket, but even that possibility has issues.

If no one uses single-precision floats, then I will suggest that we
remove them from Racket by making numbers like `3.0f0` parse as flonums
and making `real->single-flonum` raise `exn:fail:unsupported`.
Obviously, this would be a backward-incompatible change. But if it
causes little enough trouble, then it could be a good trade to avoid
problems for Racket CS and future platforms.

George Neuner

unread,
May 29, 2019, 12:33:31 PM5/29/19
to Matthew Flatt, racket users
Question: does/will Chez support converting to/from 32-bit floats for C
libraries?  It probably doesn't matter too much if Chez itself only
*operates* on 64-bit values.  But being able to pass 32-bit values I
think is important.

Machine learning is a hot topic now, and ANN often are implemented using
matrix multiplication.  A typical net involves a lot of mulitplications,
so, at least on regular CPUs, it usually IS done with 32-bit for speed. 
[On some GPUs it is done with 16-bit FP values, and Google has an 8-bit
FP chip.  But no CPUs support these small FP values, and doing it with
fixed point is a complex PITA (at least if you try to do it using SIMD
ops)].

Aside: coming from a C/C++ image processing background, I've
occasionally missed having SIMD ops native in Racket.  FFI works fine,
but calling out to a C library "feels" less natural [a bit like being
forced to use intrinsics or drop into ASM in a C program].  It would be
nice if Racket's array ops went SIMD at some point.

YMMV,
George




Dmitry Pavlov

unread,
May 29, 2019, 2:32:33 PM5/29/19
to Racket Users

> My guess is that no one uses them currently, because it's rare that
> you'd want to trade speed for *im*precision. Single-flonums in Racket
> are significantly slower than regular flonums, because they're not
> treated as a common case. The only use I can think of, and the one that
> inspired the original experiment, is to try to faithfully replicate a C
> `float` calculation in Racket, but even that possibility has issues.


To my knowledge, one reason to use single-precision numbers is
that they occupy half as much memory, which is a big deal
in e. g. video games and signal processing applications.

No, I do not use them myself in Racket.

Regards,

Dmitry

Doug Williams

unread,
May 29, 2019, 2:39:30 PM5/29/19
to Matthew Flatt, Racket Users
I support them in various packages, but I rarely use them, per se. Those packages would have to be updated, but it wouldn't be a big deal for me.

Doug

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5ceeaac9.1c69fb81.118e3.f708SMTPIN_ADDED_MISSING%40gmr-mx.google.com.
For more options, visit https://groups.google.com/d/optout.

Matthew Flatt

unread,
May 29, 2019, 4:28:21 PM5/29/19
to George Neuner, racket users
At Wed, 29 May 2019 12:33:24 -0400, George Neuner wrote:
> Question: does/will Chez support converting to/from 32-bit floats for C
> libraries?

Yes.

Konrad Hinsen

unread,
May 30, 2019, 6:10:42 AM5/30/19
to racket...@googlegroups.com
Am 29.05.19 um 17:52 schrieb Matthew Flatt:

> Does anyone use single-flonums in Racket?

Right now, no, but I have used them briefly in a past project, for
testing the impact of single-precision on a numerical algorithm.

The main reason to use single-precision floats nowadays is cutting
memory use in half, both because it is sometimes a scarce resource and
because a smaller memory footprint means better cache utilisation.
Single-precision arrays thus matter more than individual numbers. I have
even seen half-precision floats being used for the same reason. With the
current interest in "big data" and machine learning, I expect this
tendency to increase.

Konrad.

Hendrik Boom

unread,
May 30, 2019, 6:37:48 AM5/30/19
to racket...@googlegroups.com
Way back in the 60's, on a decimal computer, when memories were small, a
friend reduced floating point precision to two digits in order to save
space. Two digits isn't much, but it ws enough.

-- hendrik

Laurent

unread,
May 30, 2019, 9:03:28 AM5/30/19
to racket-users@googlegroups.com List
If no one is really relying on them as of today, then I would strongly support allowing Matthew to break things and move fast. If anyone has a real need for such a data structure it can still probably be implemented later as a third-party library, possibly extended to user-specified-precision flonums.

I suspect that if Matthew feels a need to ask about this, this means the price of backward compatibility to pay for all of us may be quite significant.

Personally, I have supported them in the past but not really used them, and I'm happy to revise my code accordingly.

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.

Robby Findler

unread,
May 30, 2019, 9:06:49 AM5/30/19
to Laurent, racket-users@googlegroups.com List
On Thu, May 30, 2019 at 8:03 AM Laurent <laurent...@gmail.com> wrote:
> I suspect that if Matthew feels a need to ask about this, this means the price of backward compatibility to pay for all of us may be quite significant.

Not one to put words in Matthew's mouth, but I presume that he is
hopeful that no one is actually using them in an important way in
their work or he wouldn't have asked.

Robby

Matthew Flatt

unread,
May 30, 2019, 9:18:29 AM5/30/19
to Konrad Hinsen, racket...@googlegroups.com
At Thu, 30 May 2019 12:10:37 +0200, Konrad Hinsen wrote:
> Am 29.05.19 um 17:52 schrieb Matthew Flatt:
>
> > Does anyone use single-flonums in Racket?
>
> Right now, no, but I have used them briefly in a past project, for
> testing the impact of single-precision on a numerical algorithm.

Thanks for replying!

Would using `math/bigfloat` (where you get to pick the precision) have
worked in that case? In a small example, I imagine you could import
`math/bigfloat` and strip the `bf` prefix using `filtered-in` to
replace the usual arithmetic operations with bigfloat variants. But I
expect that would become painful in a larger example, especially if
multiple modules are involved.

Josh Rubin

unread,
May 30, 2019, 10:15:39 AM5/30/19
to Racket Users
On Thu, May 30, 2019 at 9:03 AM Laurent <laurent...@gmail.com> wrote:
If no one is really relying on them as of today, then I would strongly support allowing Matthew to break things and move fast. If anyone has a real need for such a data structure it can still probably be implemented later as a third-party library, possibly extended to user-specified-precision flonums.

I suspect that if Matthew feels a need to ask about this, this means the price of backward compatibility to pay for all of us may be quite significant.

Personally, I have supported them in the past but not really used them, and I'm happy to revise my code accordingly.

On Thu, May 30, 2019 at 11:37 AM Hendrik Boom <hen...@topoi.pooq.com> wrote:
On Thu, May 30, 2019 at 12:10:37PM +0200, Konrad Hinsen wrote:
Am 29.05.19 um 17:52 schrieb Matthew Flatt:

Does anyone use single-flonums in Racket?
Right now, no, but I have used them briefly in a past project, for testing the impact of single-precision on a numerical algorithm. The main reason to use single-precision floats nowadays is cutting memory use in half, both because it is sometimes a scarce resource and because a smaller memory footprint means better cache utilisation. Single-precision arrays thus matter more than individual numbers. I have even seen half-precision floats being used for the same reason. With the current interest in "big data" and machine learning, I expect this tendency to increase.
Way back in the 60's, on a decimal computer, when memories were small, a friend reduced floating point precision to two digits in order to save space. Two digits isn't much, but it ws enough. -- hendrik
Adding high performance number crunching to an existing compiler and
runtime would be very hard.

Traditionally, people who need high performance floating point use a
BLAS library. Those are highly tuned to each specific architecture,
because they use platform specific techniques.

https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms

Think of memory as a slow device that is far away from the CPU. Modern
processors are horribly I/O bound - cache effects dominate everything.
Just for fun, try timing simple C programs that just read
progressively larger blocks of consecutive memory locations. There are
huge decreases in speed near the limits of each cache level.

--
Josh Rubin
jlr...@gmail.com
Hi to all my friends at NSA

Matthew Flatt

unread,
May 30, 2019, 11:43:44 AM5/30/19
to racket-users@googlegroups.com List
Based on the feedback so far, it sounds like single-flonums are a
little useful on rare occasions, but they're not needed for portable
packages.

Instead of removing single-flonum support entirely, I'm considering a
slightly less drastic change. We could add a reader parameter that
controls whether literals are ever read as single-flonums. When the
parameter is off, numbers like "3.0f0" would read as regular flonums.
The parameter would be off by default, so "3.0f0" would be a normal
flonum in a `#lang racket` module.

If the new parameter is turned on and the reader encounters a
single-flonum under Racket CS, it will raise an exception. Also, Racket
CS will always raise an exception for `real->single-flonum` or when
reading `racket/fasl`-encoded data that contains a single-flonum.

In terms of backward compatibility, this alternative is no better than
just removing single-flonums. But it keeps single-flonum functionality
available in the current Racket implementation through modest effort.

Konrad Hinsen

unread,
May 31, 2019, 3:20:22 AM5/31/19
to racket...@googlegroups.com, Matthew Flatt
Matthew Flatt <mfl...@cs.utah.edu> writes:

> At Thu, 30 May 2019 12:10:37 +0200, Konrad Hinsen wrote:
>>
>> Right now, no, but I have used them briefly in a past project, for
>> testing the impact of single-precision on a numerical algorithm.
>
> Thanks for replying!
>
> Would using `math/bigfloat` (where you get to pick the precision) have
> worked in that case? In a small example, I imagine you could import
> `math/bigfloat` and strip the `bf` prefix using `filtered-in` to
> replace the usual arithmetic operations with bigfloat variants. But I
> expect that would become painful in a larger example, especially if
> multiple modules are involved.

Right. Yes, math/bigfloat is a good substitute in my situation. Even a
better one because it permits a detailed exploration of the impact of
varying precision.

My test case was a small algorithm, implemented as four functions in a
single module, so adapting the code would not have been a problem, but
as you say, it risks being a pain for bigger code. Perhaps someone
will do #lang bigfloat one day, that would be the perfect tool for
the kind of work I did back then - but which probably few people
in the Racket community will ever do.

Konrad.

Matthew Flatt

unread,
Jun 4, 2019, 9:09:58 AM6/4/19
to racket...@googlegroups.com
Thanks for all the replies about single-flonum uses!

I've pushed the change to try out disabling single-flonum literals as
of v7.3.0.5.

Note that this change doesn't remove the concept of single-flonum
values from the language. It just removes single-flonum literals from
`#lang racket` and other languages that use the S-expression reader.


If you have a program with a single-flonum literal expression in it,
such as

3.4f5

then you can convert to a use of `real->signle-flonum`:

(real->single-flonum 3.4e5)

On a Racket variant that supports single-flonum values (like the
current version of Racket), the compiler will constant-fold that
expression to a single-flonum value, so the compiled code is the same
as writing a single-flonum literal. On a Racket variant that does
support single-flonum values, however, that expression will raise an
exception.

Here's an example in `degrees->radians` in `racket/math`:

https://github.com/racket/racket/blob/master/racket/collects/racket/math.rkt#L97

The call to `real->single-flonum` is in a `cond` clause that is guarded
with a `single-flonum?` test. Obviously, that guard will succeed only
in a Racket variant that supports single-flonum values, so we don't
need to worry about the `real->single-flonum` operation failing.

For cases where there's no natural `single-flonum?` guard, a new
`single-flonum-available?` function reports whether single-flonum
values are supported. It currently produces #t in the current version
of Racket and #f in Racket CS.

Finally, you can set the new `read-single-flonum` parameter to #t to
restore single-flonum parsing at the level of `read`. You can set
`read-single-flonum` to #t on Racket variant that does not support
single-flonum values, but `read` will raise an exception if it
encounters a single-flonum number.

Although we could make a language or a language constructor that
enables single-flonum literals by setting `real-single-flonum`, I think
we should try discouraging that, for now. Admittedly, I used a little
reader to do that in the test suite for the core single-flonum
operations, but that feels like a special case.

Hendrik Boom

unread,
Jun 5, 2019, 7:41:25 PM6/5/19
to racket...@googlegroups.com
On Tue, Jun 04, 2019 at 07:09:52AM -0600, Matthew Flatt wrote:
> Thanks for all the replies about single-flonum uses!
>
> I've pushed the change to try out disabling single-flonum literals as
> of v7.3.0.5.
>
> Note that this change doesn't remove the concept of single-flonum
> values from the language. It just removes single-flonum literals from
> `#lang racket` and other languages that use the S-expression reader.
>
>
> If you have a program with a single-flonum literal expression in it,
> such as
>
> 3.4f5
>
> then you can convert to a use of `real->signle-flonum`:
>
> (real->single-flonum 3.4e5)
>
> On a Racket variant that supports single-flonum values (like the
^^^^^^^^
> current version of Racket), the compiler will constant-fold that
> expression to a single-flonum value, so the compiled code is the same
> as writing a single-flonum literal. On a Racket variant that does
> support single-flonum values, however, that expression will raise an
^^^^^^^
> exception.

Should one of these "support"s be preceded by "not"?

>
> Here's an example in `degrees->radians` in `racket/math`:
>
> https://github.com/racket/racket/blob/master/racket/collects/racket/math.rkt#L97
>
> The call to `real->single-flonum` is in a `cond` clause that is guarded
> with a `single-flonum?` test. Obviously, that guard will succeed only
> in a Racket variant that supports single-flonum values, so we don't
> need to worry about the `real->single-flonum` operation failing.
>
> For cases where there's no natural `single-flonum?` guard, a new
> `single-flonum-available?` function reports whether single-flonum
> values are supported. It currently produces #t in the current version
> of Racket and #f in Racket CS.
>
> Finally, you can set the new `read-single-flonum` parameter to #t to
> restore single-flonum parsing at the level of `read`. You can set
> `read-single-flonum` to #t on Racket variant that does not support
> single-flonum values, but `read` will raise an exception if it
> encounters a single-flonum number.
>
> Although we could make a language or a language constructor that
> enables single-flonum literals by setting `real-single-flonum`, I think
> we should try discouraging that, for now. Admittedly, I used a little
> reader to do that in the test suite for the core single-flonum
> operations, but that feels like a special case.
>
> --
> You received this message because you are subscribed to the Google Groups "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5cf66da2.1c69fb81.baabf.95f9SMTPIN_ADDED_MISSING%40gmr-mx.google.com.

Matthew Flatt

unread,
Jun 5, 2019, 8:52:42 PM6/5/19
to Hendrik Boom, racket...@googlegroups.com
At Wed, 5 Jun 2019 19:41:19 -0400, Hendrik Boom wrote:
> On Tue, Jun 04, 2019 at 07:09:52AM -0600, Matthew Flatt wrote:
> > On a Racket variant that supports single-flonum values (like the
> ^^^^^^^^
> > current version of Racket), the compiler will constant-fold that
> > expression to a single-flonum value, so the compiled code is the same
> > as writing a single-flonum literal. On a Racket variant that does
> > support single-flonum values, however, that expression will raise an
> ^^^^^^^
> > exception.
>
> Should one of these "support"s be preceded by "not"?

Yes, the second one should be "does not support".

Thanks!


Reply all
Reply to author
Forward
0 new messages