[Trilinos-Users] Floating-point arithmetic is non-associative

Mark Hoemmen mhoemme at sandia.gov
Wed Jun 15 12:43:50 MDT 2011


On Jun 15, 2011, at 10:53 AM, Conjeepuram Subramanian, Natarajan wrote:
> Mark, I understand your logic about FP arithmetic not being associative
> and that being the reason for different answers but I am still a little
> unsure how you can guarantee it to be commutative?

The IEEE floating-point standard guarantees commutativity of individual operations.  See e.g., IEEE 754-2008, Section 10.4.  Specifically, a+b and b+a should always produce the same answer on the same machine when run twice.  This was true before IEEE 754-1985 except for a few anomalous machines.

Combinations of operations may result in apparent non-commutative behavior, depending on how rounding is performed.  (a*b) + (c*d) will produce the same result as (c*d) + (a*b) on the same machine and compiler, but different results on different machines or compilers, depending on how rounding is done.  See e.g., F. Ris, E. Barkmeyer, C. Schaffert, & P. Farkas 1993.  (Factors causing this include 80-bit vs. 64-bit temporaries, and fused multiply-add.)

> I am going to be an ignoramus and ask a naive question.
> Say a reduce with 3 procs, predefined op. as product and values a(p0),
> b(p1), c(p2). a, c very large and b very small (All floats with ac >
> max(float) and ab and bc <<< max(float)). I would think this would work
> and give correct results only if a, b, and c are in procs 0, 1, and 2 or
> some good combination thereof where the prod. ac is guaranteed to be not
> computed before ab/bc!
> 
> Is this not correct? As I know all predefined operations are assumed to
> be both associative and commutative and you can turn of commutative by
> creating your own op. but not associative. so in this case would the
> previous example be considered a case of non-associative behaviour?

Yes, it would be, if I understand correctly.  Let me restate your question, just to make sure that I understand:  

1. a and c are very large, and b is very small.  a, b, c > 0. 
2. In particular, fl(ac) = Inf, fl(ab) < Inf, fl(bc) < Inf.  
3. Compute a*b*c.

Associativity, or the lack thereof, relates to the choice of parenthesization: (ab)c  vs.  a(bc).  Commutativity only comes into play if you rearrange the terms in the product.  However, you can't get (ac)b (for example) without using associativity as well.  For example:

a(bc) -> a(cb) (commutativity) -> (ac)b (associativity)
(ab)c -> (ba)c (commutativity) -> b(ac) (associativity) -> (ac)b (commutativity)

A simpler example of non-associative floating-point behavior would be this: let e = (machine precision / 2).  Let fl( x+y ) denote the floating-point representation of the result of x + y, where x and y each can be represented exactly in floating-point arithmetic (fl(x) = x, fl(y) = y).  Then fl( (1+e) + e ) = 1, but fl( 1+(e+e) ) = 1 + 2e != 1.

mfh







More information about the Trilinos-Users mailing list