Java Numerics

Jerome Coonen jeromeabe.com
Thu Feb 13 09:57:06 PST 1997


Dear Colleagues,

This note continues the discussion of the past few weeks regarding numerics
in Java.  Because David Hough's "Comments on Java Numerics" of 2/4/97
offered useful suggestions and cast the context of the discussion in yet
another light, this note is organized loosely around Hough's comments.
Readers may wish to know that David and I had a chance to discuss these and
other issues in person on the fourth.

IEEE 754 Exceptions

We agree that some testing mechanism should be provided.  Bill Joy responded
to Hough's comments with support for "well bracketed" exception handling in
the form of try blocks:

 >> try enabling FloatingPointOverflow {
 >>     // code where overflow enabled
 >> } catch {
 >>     ...
 >> }
 
The suggestion is that, in the event the exception arose, an unspecified amount
of the try block would be excuted, but the catch block's execution would be
guaranteed.  Hough points out

 >> There would be discernible differences in implementations that
 >> examined side effects produced by basic blocks whose partial execution
 >> was interrupted by an exception, but such programs could be deemed
 >> illegal Java.

While good programming practice would dictate against dependence on the
results of a partially executed block, results may differ, whether legally
or not.  Might this not lead to exactly the kind of bit-checking between
platforms Java's designers wish to avoid?

On a smaller scale, Bill Joy proposes that the exceptions be

 >> enabled only in the code that is marked as enabled, e.g. not in the
 >> methods called by this try statement.
 
This would seem to incur a high implementation cost because of the need
to isolate the flags (static sticky bits, or possibly static trap enable
bits, on most current processors) across calls.  It also leads one to
wonder whether the programmer who wrote a statement like

z = x * exp(y);

would care whether an overflow arose in the exponential (masked by Bill
Joy's scheme) or in the product?

Operator Extension to User-defined Types

As I understand Hough's proposal, he would have operators like
"+" and "*" apply to like pairs of user-defined types, such as complex or
interval, but the operators would not support indiscriminate mixing
of different types. Programmers would use explicit casts to mix types.
Although this is the first mechanism from within the Java community that
would permit the use of extended evaluation, it would force the casting
of every float or double argument in a statement:

extended86 t = 0.0;
for (i = 0; i < N; i++)
      t += (extended86) x[i] * (extended86) y[i];

Presumably, there would be "reference" definitions of all popular types:
extended86, float_complex, double_complex, float_interval, double_interval,
etc.  In this way results could be identical across all implementations
that support the extensions.

Java is NOT a Machine-oriented Language

Hough compares Java and its reproducible results everywhere with
C, whose code can be compiled to run on virtually anything.  In the context
of numerical programs he points out that

 >> Creating and testing [C] programs that really are independent enough to
 >> run on [DEC VAX, IBM 370, Cray supercomputer, and anything conforming
 >> to IEEE 754] is an arduous task.

Hough leaps from the chaos of C's supporting every conceivable floating point
arithmetic to the conclusion that reproducibility is NECESSARY in order to
guarantee portability.  This unsupported reasoning is a basis for my dispute
about Java's numerical design.

Java's designers made a wise choice by requiring IEEE 754 conformance on all
Java platforms.  Among other things, the standard nailed down float and double
formats and specified strict rounding rules for every floating point operation.
But the standard allowed some flexibility in implementation, especially in its
recommendation that implementations support a modest amount of extended range
and precision for intermediate calculations.  Now, extended evaluation has been
scorned as incompatible with lesser systems, and its one purveyor, Intel, has
been asked to add as a feature the ability to disable any extended precision
and range on future implementations of the x86 architecture.

Nowhere in the larger discussion has there been any evidence that simple
adherence to IEEE 754 is insufficient to achieve a useful level of portability.
Instead there is the truism that if everyone can be made to agree,
no one can disagree.  And then extended accumulation is disparaged as

* dangerous in those calculations requiring exactly double precision,
* poorly implemented on some systems, and consequently unreliable, and
* of little value to purveyors of portable programs, because it's not
  available everywhere.

I have advocated adoption of the expression evaluation techniques recommended
for C9X.  They address the first two bullet items directly (where so much
harm has been done at the whims of compiler implementors).  Then there
is the matter of portability across extended-based and double-based
architectures.

One company, at least, has made the transition from extended to double
evaluation.  Apple Computer has migrated the Macintosh from the Motorola
68K to the PowerPC.  Extended evaluation was a part of the Standard Apple
Numeric Environment (SANE) dating back to the humble Apple II.  So faithful
were Apple's implementations that financial, scientific, and spreadsheet
developers could port their numerical code -- in assembly language! --
effortlessly from the Apple II to the Macintosh.  Although developers winced
when Apple dropped extended from SANE for the PowerPC, there has been no
alarm regarding the dangers of extended.

This debate needs to be joined by members of the broader numerical
community.  Just how onerous is the prospect of porting LAPACK or the
IMSL libraries to a broad family of architectures supporting IEEE 754?

The performance implications of the current Java specification drive
the argument to have Java's designers accommodate more than one IEEE 754
architecture.  According to David Hough, an expert in numerical performance,

 >> the performance penalties for adhering to Java's model are not
 >> overwhelming and could be reduced further with a few modifications
 >> in the next revisions of those architectures.

The inner product example of my original note showed that memory traffic
nearly doubled for compiled x86 code forced to adhere to Java's model.
Given that this penalty is suffered by users whose processors dominate
the market by orders of magnitude, one might expect this to be of more
than "not overwhelming" concern.  Other examples involve elementary
functions, several of which are provided at high accuracy and speed on
x86 machines.

Sometimes performance arguments are expressed relative to the "high-end
market," where RISC cpus rather than CISC x86s currently dominate.
On the one hand it's natural to expect high-end users not to be overly
concerned with problems on other users' processors; on further inspection,
however, it turns out that the most performance-hungry users in the elite
workstation market are interested in FORTRAN, not C or Java.  This does
not lead to compelling arguments about Java across a breadth of networked
platforms.

System designs have always involved a balance of speed and accuracy.
Although historically some painful decisions have been made in the
name of speed, Java's designers have reached the other extreme -- and
not even in the name of accuracy, only sameness at all costs.

As Java finds wider numerical use, the pressure for higher performance --
without sacrificing a bit of IEEE 754 conformance -- will rise.
Implementors wishing to make a sale, or users who want to get their
work done, will be forced to decide whether one arbitrary "reference"
version of an elementary function or a LINPACK BLAS serves their
needs best.  The decision about what is truly "100% pure" Java may
become clouded by the legitimate demands of numerical users and by
mathematical arguments that fast, accurate libraries on top of 
100% pure IEEE 754 arithmetic lead to a more desirable mix of
performance, accuracy, and portability.

-Jerome Coonen




More information about the Numeric-interest mailing list