digitalmars.D.learn - double vs real
- Shriramana Sharma (14/14) May 30 2013 Hello. I like that D exposes to me the real type to maximally utilize
- Diggory (8/22) May 30 2013 Since D does all operations at highest possible precision anyway
- Shriramana Sharma (22/25) May 30 2013 r
- Marco Leise (51/74) May 30 2013 for
- bearophile (12/25) May 30 2013 If you have to store many reals, they require more memory than
- Joseph Rushton Wakeling (4/6) May 30 2013 In my experience, using real slows things down, though the degree depend...
- Timon Gehr (4/8) May 31 2013 If double uses xmm registers and real uses the fpu registers (as is
- Shriramana Sharma (9/12) May 31 2013 Hi can you clarify that? I'm interested because I'm running a 64 bit
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/13) May 31 2013 I am interested in the answer too. Meanwhile, can you run a test and see...
- John Colvin (10/24) May 31 2013 int, long, float, double etc. are all of size 2^n. That means
- Timon Gehr (3/29) May 31 2013 What I was talking about also holds for scalar code without usage of any...
- Timon Gehr (25/32) May 31 2013 Depends. Two useful numbers to classify performance characteristics of
- Marco Leise (18/28) May 30 2013 If you have large amounts of values and want to work on them
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
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
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=rdouble or float) it only makes a difference when the value is being store=dto 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
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:forSince D does all operations at highest possible precision anyway (even =reddouble or float) it only makes a difference when the value is being sto=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)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.)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. :pSo 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
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
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
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
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=ardon 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
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:standardIf double uses xmm registers and real uses the fpu registers (as isI 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, Alion 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?
May 31 2013
On Friday, 31 May 2013 at 16:17:28 UTC, Ali Çehreli wrote:On 05/31/2013 04:28 AM, Shriramana Sharma wrote: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.On Fri, May 31, 2013 at 4:31 PM, Timon Gehr<timon.gehr gmx.ch> wrote:(as is standardIf double uses xmm registers and real uses the fpu registersof realon x64), then double multiplication has twice the throughput64 bitmultiplication on recent intel microarchitectures.Hi can you clarify that? I'm interested because I'm running asystem. What does twice the throughput mean? double is faster?I am interested in the answer too.
May 31 2013
On 05/31/2013 09:08 PM, John Colvin wrote:On Friday, 31 May 2013 at 16:17:28 UTC, Ali Çehreli wrote:What I was talking about also holds for scalar code without usage of any packed instructions.On 05/31/2013 04:28 AM, Shriramana Sharma wrote: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.On Fri, May 31, 2013 at 4:31 PM, Timon Gehr<timon.gehr gmx.ch> wrote:(as is standardIf double uses xmm registers and real uses the fpu registersof realon x64), then double multiplication has twice the throughput64 bitmultiplication on recent intel microarchitectures.Hi can you clarify that? I'm interested because I'm running asystem. What does twice the throughput mean? double is faster?I am interested in the answer too.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
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: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/#manualsIf 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?
May 31 2013
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