The End of Numeric Error: An interview with John L. Gustafson
ubiquity.acm.org
ubiquity.acm.org
Using pyunum, repeatedly rotate the point (1,0) by 45 degrees. Print out the X coordinate every 8 rotations. Mathematically, the value printed each time should be exactly 1. Unfortunately, after just 79 iterations, the unum covers the range (-27352064, 27352064)! This includes the correct result but is useless.
A similar program using Python floats (i.e., platform doubles) prints 0.9999999999999937 at step 79 and runs in 1/540 of the time on my oldish core2 notebook. (or 0.9999999999371962 at step 799999 in less than 1/10 of the time of the 79 unum steps)
from unum import *
a = divideu(x2u(1), sqrtu(x2u(2)))
x, y = x2u(1), x2u(0)
for i in range(80):
x, y = timesu(minusu(x, y), a), timesu(plusu(x, y), a)
if i % 8 == 7: print i, view(x) import unum_config
unum_config.e = 3
unum_config.f = 9
This gives 2^3=8 bits for the exponent, and 2^9=512 bits for the fraction. The default values for e and f are 3 (8 bits) and 4 (16 bits) respectively.The idea with unums is that your program sees the unacceptable bounds, and recomputes with higher precision.
Comparing speeds is very unfair: one implementation is hardware which has received maybe $100B-worth of optimization over decades, the other is one guy's python script.
In this implementation, 9 seems to be the maximum value for f: if I set it to 10 unum fails to import because it tries to divide a float by too large an integer. And 4 seems to be the maximum practical value for e. At e=5, initialization of unum takes over two minutes and 250M of memory, probably because it's computing the largest possible value in that floating point scheme.
It would certainly be nice to have more pythonic port.
I think the book is nice, but popularizing "unum"s with a book targeting non-experts feels like skipping an important step in due process, given the grand claims that are being made.
Incidentally, I submitted a short version to the ARITH23 conference detailing how IEEE 754 could be repaired to give bit-identical results on different systems, and they had it reviewed by three reviewers, one who liked it, and the other two who served on the IEEE 754 committee and trashed it for some pretty silly reasons, like using the word "subnormal" instead of "denormal".
There is no easy way to boil the ocean, but I'm trying.
How can this be implemented efficiently? If there's a cap on the maximum number of bits (eg, 64), why not just use that maximum number all the time, and not have to worry about shuffling things around (bitwise!) in memory?
Edit: Link has been changed to a more in depth ACM interview! I suppose this is a floating point format that makes the intervals more explicit by changing size to account for significant digits.
Also, to enable round-tripping with string representations, your printf/scanf pair has to discriminate between exact and inexact versions of, for example, 3/4. If you don't, every string you read in (e.g. from XML (including reading modern spreadsheet data), json, or from user input, will have to have the 'exact' bit cleared. I guess so many numbers will be inexact that it turns out to have close to zero information content (in other words: adding it to your numbers is a waste of space)
Or are you suggesting that, when computing 1/3, this number format picks the best representation for a given number of bits, keeping the 'exact' bit, for 1/3, and then magically decides that, say, 85/256 and 'exact' must be 1/3, and not 85/256, or whatever other expression that could be computed exactly gets close to it?
I don't see it gain wide acceptance. If your problem is fixed-num, use a bignum library. If it is not, chances are you will meet a number that isn't representable in this format very, very soon (1/3, 1/5, sqrt(2), PI, etc.)
The moment you do, you will have to decide to how many bits of precision you want to compute that inexact number. Problem is that you cannot make that choice, unless you know exactly what you intend to do with the number. I bet most users will choose a format that their hardware handles natively: IEEE.
There may be edge cases in numerical computing that benefit from this, especially when problems are ill-conditioned, but even there, I expect people to convert to conventional IEEE on the outside of their API. Also, I'm not sure there is much room in this space below quad-width floats (but I am not an expert)
BCD as "binary coded decimal" is, effectively, useless. Even arbitrary precision libraries tend to be faster than BCD.
"decimal floating point", which is what I think you meant, just changes what isn't representable. Instead of 1/5 causing a problem, 1/3 causes a problem.
The "classic" problem about this is matrix operations. Specifically, matrix inversion. You can use interval arithmetic on matrix inversion, and you find that the intervals blow up to almost infinity after just a couple of operations even though the center of the interval is actually pretty close to the solution. Of course, the reverse also holds: while most matricies invert relatively cleanly, there are always pathological cases that really do need humungous precision to invert.
PS: Don't know why you were getting downvoted as you asked a legitimate question.
These "unums" have been posted before, e.g. https://news.ycombinator.com/item?id=11410349
>Because the Julia language is particularly good at adding new data types without sacrificing speed, several people jumped on making a port to Julia, including the MIT founders of that language.
I'm really impressed with the Julia language so far and considering implementing some quantum chemistry models for many-body systems (Hartree-Fock and probably Coupled Cluster if I ever get that far). Mostly because a) Julia looks fun, b) FORTRAN is still king of speed (which I'll need all I can get of) but is a pain to write and c) the alternative to FORTRAN is C(++), where being OO isn't that much of a bonus. And Julie looks fun to write.
I'm currently writing unit and continuous tests for a computer chip that is being simulated - basically julia does the computation in x86, which suggests what the IEEE result should be, and then generates the assembler and passes it on to the assembler.
It probably could have been easily written in something like python, ruby, or perl, but the modularness of Julia, functional programming, and (optional) explicit typing result in easy-to-read code and a sense of security that there are no shenanigans going on under the hood with the type system.
Another cool thing is for more complicated code (working on a demonstration fast fourier transform) is that I can write the core FFT algorithm as a function with macros, and by swapping a different include that defines the macros differently, it can either run it as a virtual processor using internal Julia arrays that represent the memory and register files, or build up a file that contains the assembler code. Again, this is obviously possible in other languages [0], but Julia makes it look nice and easy to comprehend.
[0] I'm thinking that ruby (especially with it's DSL-eyness) would be really good for this, but I abandoned ruby when it became too difficult (I'm lazy and dense) to install the correct version on my own computer much less figure out how to install it on a server for other people to use.
I'm surprised that, with the restrict keyword, one would see better code gen from Fortran than C. Isn't the lack of aliasing Fortran's primary advantage?
If you're a researcher first and a software developer second (which I suspect is true of gp), the last thing you want to do is get into the weeds of inspecting gcc assembly to figure out where you didn't put a "restrict" that you should've.
I really like Haskell. Even with all the effort i've put into it, it seems like i've barely scratched the surface if i want performance. sigh
https://github.com/rpmuller/pyquante2/tree/master/julia
Let me know if you do want to do some quantum chemistry coding. It would be good for my soul to revisit some of my PhD roots...
Also, some floating point ops that use pade approximants (most log algorithms, sin, cos) lose onoe or two precision points (versus half for arithmetic ops) of floating point accuracy.
If you're using IEEE floating points, your systems will silently fail and (rarely) give an error like NaN. IEEE intervals will work, but often give a diagnostically useless answer. Unums have characteristic signatures that hint where to look to find the problematic calculation. You can then backtrack and redo the calculation at a higher precision and drop back to the standard precision as necessary. This is, of course, automatable.
Mostly false; see https://www.cs.berkeley.edu/~wkahan/Mindless.pdf
It is true that an arbitrary, independent sequence of n floating point operations can potentially lose up to 2n bits of precision. However, it is false that most scientific computing code has such structure. On the contrary, the loss of precision in numerical algorithms can be estimated quite well using standard techniques of error analysis, especially when there is underlying matrix structure to exploit. The growth of error in properly written numerical code should NOT grow exponentially with the number of floating point operations. It should be bounded by intrinsic properties of the underlying matrix, such as its condition number or spectral norm.
But anything which uses matrices (aka. systems of linear differential equations), always runs into some pathological cases. Quite often, they aren't even uncommon.
Systems which have vastly different time constants in the same system are ALWAYS a problem. Simulating RF circuits or phase locked loops is always an issue.
Computational fluid dynamics always has boundary conditions that challenge infinity/zero and drive the solver crazy.
Something as pedestrian as simulating basic cotton cloth accurately is problematic (the warp/weft redistributes energy on a much faster time scale than gravity pulls the cloth down).
A lot of people did a lot of research and put in a lot of programming hours to make solving these problems relatively easy without understanding the gory details.
I'm skeptical that changing how we represent the numbers will help - when the physics are icky, they're icky.
More problematic is that when a matrix is ill-conditioned it may not be all that helpful to have "an answer" since the ill-conditioning tells you there are many solutions closely satisfying the system of equations.
I've implemented a few DE solvers and sparse matrix implementations before. I think sparse matrices is one case where it would help.
[1] http://www.johngustafson.net/presentations/Multicore2016-JLG... (see example starting p.10)
In statistics numbers often get very small because they represent probabilities. Sometimes they transform into the log domain, but that has a lot of disadvantages. You lose zero, negative numbers, addition is difficult, and you get vastly more precision near zero than near one.