www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - double vs real

reply Shriramana Sharma <samjnaa gmail.com> writes:
Hello. I like that D exposes to me the real type to maximally utilize
the machine's numerical precision. Since I am writing a program
(currently in C++ but I am thinking of moving to D) that has to handle
lots of fractional numbers (calculating offset curves and such) I am
wondering whether/when I should real instead of double or even any
arguments in favour of staying with double (compatibility with
C/C++?). Any pointers appreciated please? I checked the FAQ but it
doesn't seem to mention this.

Thanks!

--=20
Shriramana Sharma =E0=AE=B6=E0=AF=8D=E0=AE=B0=E0=AF=80=E0=AE=B0=E0=AE=AE=E0=
=AE=A3=E0=AE=B6=E0=AE=B0=E0=AF=8D=E0=AE=AE=E0=AE=BE =E0=A4=B6=E0=A5=8D=E0=
=A4=B0=E0=A5=80=E0=A4=B0=E0=A4=AE=E0=A4=A3=E0=A4=B6=E0=A4=B0=E0=A5=8D=E0=A4=
=AE=E0=A4=BE
May 30 2013
next sibling parent reply "Diggory" <diggsey googlemail.com> writes:
On Thursday, 30 May 2013 at 16:18:44 UTC, Shriramana Sharma wrote:
 Hello. I like that D exposes to me the real type to maximally 
 utilize
 the machine's numerical precision. Since I am writing a program
 (currently in C++ but I am thinking of moving to D) that has to 
 handle
 lots of fractional numbers (calculating offset curves and such) 
 I am
 wondering whether/when I should real instead of double or even 
 any
 arguments in favour of staying with double (compatibility with
 C/C++?). Any pointers appreciated please? I checked the FAQ but 
 it
 doesn't seem to mention this.

 Thanks!
Since D does all operations at highest possible precision anyway (even for double or float) it only makes a difference when the value is being stored to memory and then read back again. I would recommend aliasing double or real to a custom name and then using that. Then when you're done you can easily switch between them and see how it affects precision in your particular case and decide what's best.
May 30 2013
parent reply Shriramana Sharma <samjnaa gmail.com> writes:
Thanks to all who replied.

On Thu, May 30, 2013 at 10:07 PM, Diggory <diggsey googlemail.com> wrote:
 Since D does all operations at highest possible precision anyway (even fo=
r
 double or float) it only makes a difference when the value is being store=
d
 to memory and then read back again.
But isn't this true for even C/C++ i.e. that the actual FP calculation is done at a higher precision than what is exposed? And this is so that rounding errors may be minimized? (I mean, I can see how repeated multiplications and square roots and such would totally devalue the LSBs of a double if calculations were done only in double precision.) So IIUC the only thing D does newly is to actually *expose* the full machine precision for those who want it? But really how much use is that? Because a friend of mine was warning (in general, not particularly about D) against falling into the illusion of higher precision =3D=3D higher accuracy. If I use 80-bit FP as my data storage type, then only if an even higher precision were actually used inside the processor for calculations would the LSBs retain their significance, right? So in the end what is real useful for? --=20 Shriramana Sharma =E0=AE=B6=E0=AF=8D=E0=AE=B0=E0=AF=80=E0=AE=B0=E0=AE=AE=E0= =AE=A3=E0=AE=B6=E0=AE=B0=E0=AF=8D=E0=AE=AE=E0=AE=BE =E0=A4=B6=E0=A5=8D=E0= =A4=B0=E0=A5=80=E0=A4=B0=E0=A4=AE=E0=A4=A3=E0=A4=B6=E0=A4=B0=E0=A5=8D=E0=A4= =AE=E0=A4=BE
May 30 2013
parent Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 31 May 2013 07:02:11 +0530
schrieb Shriramana Sharma <samjnaa gmail.com>:

 Thanks to all who replied.
=20
 On Thu, May 30, 2013 at 10:07 PM, Diggory <diggsey googlemail.com> wrote:
 Since D does all operations at highest possible precision anyway (even =
for
 double or float) it only makes a difference when the value is being sto=
red
 to memory and then read back again.
=20 But isn't this true for even C/C++ i.e. that the actual FP calculation is done at a higher precision than what is exposed? And this is so that rounding errors may be minimized? (I mean, I can see how repeated multiplications and square roots and such would totally devalue the LSBs of a double if calculations were done only in double precision.)
Well more or less. When C was designed PCs didn't have 80-bit floating point (real). So the specification read like this: =C2=BB All floating arithmetic in C is carried out in double-precision; whenever a float appears in an expression it is lengthened to double by zero-padding its fraction. =C2=AB The C runtime achieves this by switching a FPU setting for internal precision from real - the default - to double. So in C, double * double will in deed NOT use the full FPU precision. Later specifications (~1998) allowed for greater precision in C just like D does it. But I imagine few C compilers actually do this since it breaks code and is platform specific. E.g. PowerPC has 128-bit as the maximum precision, so the same program running on x86 and PowerPC using the full precision might give different results! So to summarize, C typically gives you the same results across platforms, D encourages compiler implementers to use a higher precision. (http://dlang.org/float.html)
 So IIUC the only thing D does newly is to actually *expose* the full
 machine precision for those who want it?
Well there is the switch for the internal FPU precision and there is data types (like real). Most C compilers *do* offer 'real' data types under the name 'long double' and you can also change the FPU precision with intrinsics or compiler switches. So if you really want it you can get the same precision in C as in D. But you have to specialize for different compilers.
 But really how much use is
 that? Because a friend of mine was warning (in general, not
 particularly about D) against falling into the illusion of higher
 precision =3D=3D higher accuracy. If I use 80-bit FP as my data storage
 type, then only if an even higher precision were actually used inside
 the processor for calculations would the LSBs retain their
 significance, right?
It totally depends on the values and operations you apply on them. If you add two values which have the same exponent and their mantissas can be added without changing this exponent, you have 100% accuracy. If you do more complex arithmetics, accuracy is lost and your friend is right. But you seem to care so much about precision and not at all about speed or memory consumption that you will probably sleep better knowing that you might have saved one or two bits of precision from some calculations. :p
 So in the end what is real useful for?
For everything that's not stored. ;) Function returns and variables that the compiler will likely keep in a FPU register: real foo(real x, real y) { real z =3D x + y; return z; } (If you use float or double for variable z, the compiler is forced to insert instructions that will round down and store the FP value in memory just to load it back up into an FPU register for the return.) --=20 Marco
May 30 2013
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Shriramana Sharma:

 Hello. I like that D exposes to me the real type to maximally 
 utilize
 the machine's numerical precision. Since I am writing a program
 (currently in C++ but I am thinking of moving to D) that has to 
 handle
 lots of fractional numbers (calculating offset curves and such) 
 I am
 wondering whether/when I should real instead of double or even 
 any
 arguments in favour of staying with double (compatibility with
 C/C++?). Any pointers appreciated please? I checked the FAQ but 
 it
 doesn't seem to mention this.
If you have to store many reals, they require more memory than doubles (how much is relative to the operating system). Regarding speed in theory double and real should give the same, but in practice theory and practice often differ. As suggested, use an alias like: alias FP = real; And switch from double and real, and take a look at the differences. But don't perform such switch at the end, do it now and then to be sure everything keeps working correctly. Bye, barophile
May 30 2013
next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 05/30/2013 06:45 PM, bearophile wrote:
 Regarding speed in theory double and real
 should give the same, but in practice theory and practice often differ.
In my experience, using real slows things down, though the degree depends on use-case (mine involves lots of iterations and calculations over different arrays full of floating-point numbers).
May 30 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/30/2013 06:45 PM, bearophile wrote:
 ...
 If you have to store many reals, they require more memory than doubles
 (how much is relative to the operating system). Regarding speed in
 theory double and real should give the same, ...
If double uses xmm registers and real uses the fpu registers (as is standard on x64), then double multiplication has twice the throughput of real multiplication on recent intel microarchitectures.
May 31 2013
parent reply Shriramana Sharma <samjnaa gmail.com> writes:
On Fri, May 31, 2013 at 4:31 PM, Timon Gehr <timon.gehr gmx.ch> wrote:
 If double uses xmm registers and real uses the fpu registers (as is stand=
ard
 on x64), then double multiplication has twice the throughput of real
 multiplication on recent intel microarchitectures.
Hi can you clarify that? I'm interested because I'm running a 64 bit system. What does twice the throughput mean? double is faster? --=20 Shriramana Sharma =E0=AE=B6=E0=AF=8D=E0=AE=B0=E0=AF=80=E0=AE=B0=E0=AE=AE=E0= =AE=A3=E0=AE=B6=E0=AE=B0=E0=AF=8D=E0=AE=AE=E0=AE=BE =E0=A4=B6=E0=A5=8D=E0= =A4=B0=E0=A5=80=E0=A4=B0=E0=A4=AE=E0=A4=A3=E0=A4=B6=E0=A4=B0=E0=A5=8D=E0=A4= =AE=E0=A4=BE
May 31 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/31/2013 04:28 AM, Shriramana Sharma wrote:

 On Fri, May 31, 2013 at 4:31 PM, Timon Gehr <timon.gehr gmx.ch> wrote:
 If double uses xmm registers and real uses the fpu registers (as is 
standard
 on x64), then double multiplication has twice the throughput of real
 multiplication on recent intel microarchitectures.
Hi can you clarify that? I'm interested because I'm running a 64 bit system. What does twice the throughput mean? double is faster?
I am interested in the answer too. Meanwhile, can you run a test and see which type is faster on your system and then report here. :) Thanks, Ali
May 31 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 31 May 2013 at 16:17:28 UTC, Ali Çehreli wrote:
 On 05/31/2013 04:28 AM, Shriramana Sharma wrote:

 On Fri, May 31, 2013 at 4:31 PM, Timon Gehr
<timon.gehr gmx.ch> wrote:
 If double uses xmm registers and real uses the fpu registers
(as is standard
 on x64), then double multiplication has twice the throughput
of real
 multiplication on recent intel microarchitectures.
Hi can you clarify that? I'm interested because I'm running a
64 bit
 system. What does twice the throughput mean? double is faster?
I am interested in the answer too.
int, long, float, double etc. are all of size 2^n. That means they can be neatly packed in to SIMD registers (e.g. XMM0-XMM15 on x86_64) and can be operated on in parallel, providing very large speedups in some cases. real, on the other hand - on x86/64 - is 80bits and as such doesn't fit in to the same scheme. There are also differences to do with calling conventions that can make different types slower/faster, but this is very dependant on the exact usage and normally only significantly affects small functions that can't be inlined IME.
May 31 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/31/2013 09:08 PM, John Colvin wrote:
 On Friday, 31 May 2013 at 16:17:28 UTC, Ali Çehreli wrote:
 On 05/31/2013 04:28 AM, Shriramana Sharma wrote:

 On Fri, May 31, 2013 at 4:31 PM, Timon Gehr
<timon.gehr gmx.ch> wrote:
 If double uses xmm registers and real uses the fpu registers
(as is standard
 on x64), then double multiplication has twice the throughput
of real
 multiplication on recent intel microarchitectures.
Hi can you clarify that? I'm interested because I'm running a
64 bit
 system. What does twice the throughput mean? double is faster?
I am interested in the answer too.
int, long, float, double etc. are all of size 2^n. That means they can be neatly packed in to SIMD registers (e.g. XMM0-XMM15 on x86_64) and can be operated on in parallel, providing very large speedups in some cases. real, on the other hand - on x86/64 - is 80bits and as such doesn't fit in to the same scheme.
What I was talking about also holds for scalar code without usage of any packed instructions.
 There are also differences to do with calling conventions that can make
 different types slower/faster, but this is very dependant on the exact
 usage and normally only significantly affects small functions that can't
 be inlined IME.
May 31 2013
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/31/2013 01:28 PM, Shriramana Sharma wrote:
 On Fri, May 31, 2013 at 4:31 PM, Timon Gehr <timon.gehr gmx.ch> wrote:
 If double uses xmm registers and real uses the fpu registers (as is standard
 on x64), then double multiplication has twice the throughput of real
 multiplication on recent intel microarchitectures.
Hi can you clarify that? I'm interested because I'm running a 64 bit system. What does twice the throughput mean? double is faster?
Depends. Two useful numbers to classify performance characteristics of machine instructions are latency and reciprocal throughput. Modern out-of-order processors are pipelined. I.e. instructions may take multiple cycles to complete, and multiple instructions may run through different stages of the pipeline at the same time. Latency: The time taken from the point the point where all inputs are available to the point where all outputs are available. Reciprocal throughput: The minimum delay between the start of two instructions of the same kind. Multiplying doubles in an xmm register has latency 5 and reciprocal throughput 1 (on recent intel microarchitectures). Multiplying 'reals' in an fpu register has latency 5 and reciprocal throughput 2. Therefore, doubles allow more instruction level parallelism (ILP). However, if you have eg. a computation like this one: b = a*b*c*d; Then there will not be a difference in runtime, as all instructions depend on a previous result. On the other hand, if you reassociate the expression as follows: b = (a*b)*(c*d); Then double will be one cycle faster, since the second mult can be started one cycle earlier, and hence the third one can also start one cycle earlier. If you are interested, more information is available here: http://agner.org/optimize/#manuals
May 31 2013
prev sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Thu, 30 May 2013 17:47:14 +0530
schrieb Shriramana Sharma <samjnaa gmail.com>:

 Hello. I like that D exposes to me the real type to maximally utilize
 the machine's numerical precision. Since I am writing a program
 (currently in C++ but I am thinking of moving to D) that has to handle
 lots of fractional numbers (calculating offset curves and such) I am
 wondering whether/when I should real instead of double or even any
 arguments in favour of staying with double (compatibility with
 C/C++?). Any pointers appreciated please? I checked the FAQ but it
 doesn't seem to mention this.
 
 Thanks!
If you have large amounts of values and want to work on them fast use floats for storage since currently computers have more processing power than memory bandwidth. If you return numbers from functions use real. This allows the compiler to return them as-is from the FPU, whereas double and float require an additional rounding step. The same may apply to temporary variables. Where the amount of numbers is smaller and they fit into CPU cache, the memory bandwidth doesn't matter. 32-bit CPUs work the fastest with floats, whereas 64-bit CPUs work efficiently with doubles. My tip is to use real everywhere in calculations until it comes to storing the results for later use where doubles are more compact. -- Marco
May 30 2013