c# - Coercing floating-point to be deterministic in .NET? -
i've been reading lot floating-point determinism in .net, i.e. ensuring same code same inputs give same results across different machines. since .net lacks options java's fpstrict , msvc's fp:strict, the consensus seems be there no way around issue using pure managed code. c# game ai wars has settled on using fixed-point math instead, cumbersome solution.
the main issue appears clr allows intermediate results live in fpu registers have higher precision type's native precision, leading impredictably higher precision results. msdn article clr engineer david notario explains following:
note current spec, it’s still language selection give ‘predictability’. the language may insert conv.r4 or conv.r8 instructions after every fp operation ‘predictable’ behavior. obviously, expensive, , different languages have different compromises. c#, example, nothing, if want narrowing, have insert (float) , (double) casts hand.
this suggests 1 may accomplish floating-point determinism inserting explicit casts every look , sub-expression evaluates float. 1 might write wrapper type around float automate task. simple , ideal solution!
other comments suggest isn't simple. eric lippert stated (emphasis mine):
in version of runtime, casting float explicitly gives different result not doing so. when explicitly cast float, c# compiler gives hint runtime "take thing out of high precision mode if happen using optimization".
just "hint" runtime? c# spec stipulate explicit cast float causes insertion of conv.r4 in il? clr spec stipulate conv.r4 instruction causes value narrowed downwards native size? if both of these true can rely on explicit casts provide floating point "predictability" explained david notario.
finally, if can indeed coerce intermediate results type's native size, plenty guarantee reproducibility across machines, or there other factors fpu/sse run-time settings?
just "hint" runtime?
as conjecture, compiler tracks whether conversion double or float nowadays in source code, , if was, inserts appropriate conv opcode.
does c# spec stipulate explicit cast float causes insertion of conv.r4 in il?
no, assure there unit tests in compiler test cases ensure does. though specification not demand it, can rely on behaviour.
the specification's comment floating point operation may done in higher precision required @ whim of runtime, , can create results unexpectedly more accurate. see section 4.1.6.
does clr spec stipulate conv.r4 instruction causes value narrowed downwards native size?
yes, in partition i, section 12.1.3, note you have looked yourself rather asking net you. these specifications free on web.
a question didn't inquire should have:
is there operation other casting truncates floats out of high precision mode?
yes. assigning static field, instance field or element of double[]
or float[]
array truncates.
is consistent truncation plenty guarantee reproducibility across machines?
no. encourage read section 12.1.3, has much interesting on subject of denormals , nans.
and finally, question did not inquire should have:
how can guarantee reproducible arithmetic?
use integers.
c# .net floating-point ieee-754
No comments:
Post a Comment