   double arithmetic faster than float
  Hi,I did some profiling on my machine today and got a surprising result. Adding, multiplying and dividing double is as least twice faster than float! How can this be? Is it because I'm using a 64-bit CPU? But I'm using 32-bit windows!So what exactly is the determining factor here?Here is the simple routine I used for the testing:float f = 0, ff = 1;time_t time = GetTickCount();for (int count = 0; count < 100000000; ++count, ff += 1)   f += ff;time = GetTickCount() - time;cout << "\nfloat: " << time << "ms, result = " << f;
  Your test is invalid. You're not running it in release mode. How do I know? Because in release mode, that loop should be completely optimised out.Also, GetTickCount() is extremely inaccurate, and is completely useless as a profiling timer.   ;Quote:Original post by snootyHi,I did some profiling on my machine today and got a surprising result. Adding, multiplying and dividing double is as least twice faster than float! How can this be? Is it because I'm using a 64-bit CPU? But I'm using 32-bit windows!So what exactly is the determining factor here?Here is the simple routine I used for the testing:*** Source Snippet Removed ***How much time  did each version take? (GetTickCount isn't all that accurate, so unless it takes a fairly long time, your result is useless)There a a million reasons why float might not be faster than double. If it uses double internally, and then has to cast to and from float to store each result, that'd obviously be a slowdown. Or if the FPU works at 80bit precision internally anyway, float or double wouldn't really make a difference.Depends on the FPU settings.Oh, and you could simply check your CPU manufacturer's manuals to see the actual latency and throughput of float/double instructions.And then, look at the assembly generated by your program, and see what it actually does.Without bothering to look it up, I seem to recall that on Athlon 64 at least, the x87 versions of floating-point instructions are equally fast for float and double. The SSE versions are faster for float. On your CPU? Who knows? But most likely, the answer is exactly what code the compiler is generating.Quote:Your test is invalid. You're not running it in release mode. How do I know? Because in release mode, that loop should be completely optimised out.Hmm, why? He updates the intermediate result every iteration, and outputs the final result in the end, so it can't completely remove the loop.But yeah, writing proper performance benchmarks isn't the easiest thing in the world.   ;Quote:Original post by SpoonbenderQuote:Your test is invalid. You're not running it in release mode. How do I know? Because in release mode, that loop should be completely optimised out.Hmm, why? He updates the intermediate result every iteration, and outputs the final result in the end, so it can't completely remove the loop.But yeah, writing proper performance benchmarks isn't the easiest thing in the world.Hmm, you might be right actually. I assumed the compiler would see that there's no function calls or variable references in there, and it could all be determined at compile time.The best way to profile this would (I think) be with assembly to make sure the compiler doesn't optimise it away, RDTSC for timing (make sure you force the thread / process to one core), and critical process and thread priority.   ;  Thank you for the replies.For addition, float takes some 600ms and double takes some 200ms.I've tried increasing the repetition count so that float takes some 6000ms, and double takes some 2000ms. So I guess GetTickCount() inaccuracy can be ruled out.Unfortunately I don't know any assembly and I probably have thrown my CPU manual out... I guess I'll have to leave it at that.   ;  The compiler is outputting poor code for the float version. It loads and stores f and ff from/to memory every iteration, where as the double version keeps both on the FP stack until the end.   ;  Well, this is what I got. One bad thing I am doing is converting from int64 to double to be able to display results in seconds and so on, and this seems to produce weird results such as negative numbers.My computer is a laptop with AMD Turion 64 X2 Mobile, running 32-bit Windows.My conclusion based on this data: double and float are just about as peformant with simple math operations, so you might as well use double if memory space is of no concern.-=-=-=-=-=-=-=-=-Running in Debug Mode.Testing float first, then double.float test:  0.027 seconds (26.52 milliseconds, 26515939.9 nanoseconds)double test: 0.034 seconds (34.14 milliseconds, 34142607.5 nanoseconds)double was 1.29 times (128.8%) faster than float.Press any key to continue . . .--------------------------------------------------Running in Debug Mode.Testing double first, then float.float test:  0.027 seconds (26.65 milliseconds, 26653946.2 nanoseconds)double test: 0.034 seconds (33.87 milliseconds, 33870785.3 nanoseconds)double was 1.27 times (127.1%) faster than float.Press any key to continue . . .--------------------------------------------------Testing float first, then double.float test:  -1.249 seconds (-1249.20 milliseconds, -1249197709.8 nanoseconds)double test: -1.189 seconds (-1189.39 milliseconds, -1189388226.4 nanoseconds)double was 0.95 times (95.2%) faster than float.Press any key to continue . . .--------------------------------------------------Testing float first, then double.float test:  -1.157 seconds (-1157.42 milliseconds, -1157418045.5 nanoseconds)double test: -1.141 seconds (-1140.76 milliseconds, -1140763584.4 nanoseconds)double was 0.99 times (98.6%) faster than float.Press any key to continue . . .--------------------------------------------------Testing double first, then float.float test:  -0.000 seconds (-0.00 milliseconds, -64.1 nanoseconds)double test: -3.098 seconds (-3098.36 milliseconds, -3098359270.7 nanoseconds)float was 0.00 times (0.0%) faster than double.Press any key to continue . . .-=-=-=-=-=-=-=-=-Here's the code to the program, so anyone interested can tune it and run it// FloatVersusDouble.cpp : Defines the entry point for the console application.////// Includes//#include <cstdio>// using printf#include <tchar.h>// using TCHAR#include <crtdbg.h>// using _ASSERT#include <windows.h>   // using QueryPerformanceCounter/Frequency//// SimpleProfiler class//class SimpleProfiler{private:LARGE_INTEGER m_nPerformanceFrequency;LARGE_INTEGER m_nProfileStartTime;public:SimpleProfiler(void){_ASSERT(QueryPerformanceFrequency(&m_nPerformanceFrequency));};public:void Begin(void){_ASSERT(QueryPerformanceCounter(&m_nProfileStartTime));};double End(void){LARGE_INTEGER nProfileEndTime;_ASSERT(QueryPerformanceCounter(&nProfileEndTime));LARGE_INTEGER nDifference;nDifference.QuadPart = nProfileEndTime.QuadPart - m_nProfileStartTime.QuadPart;return double(nDifference.QuadPart) / double(m_nPerformanceFrequency.QuadPart);}};//// Entry Point//int _tmain(int argc, _TCHAR* argv[]){#define DOUBLE_FIRSTSimpleProfiler profiler;#ifdef DOUBLE_FIRSTgoto doubletest;#endiffloattest:// Run float testfloat f = 0.0f;profiler.Begin();for(int j = 0; j < 1000000; j++){for(int n = j; n < 1000000; n++){f = ((f * 24.0f - 32.0f) / 5.0f) * 0.1f;}}double dFloatTime = profiler.End();#ifdef DOUBLE_FIRSTgoto results;#endif// Run double testdoubletest:double d = 0.0;profiler.Begin();for(int j = 0; j < 1000000; j++){for(int n = j; n < 1000000; n++){d = ((d * 24.0 - 32.0) / 5.0) * 0.1;}}double dDoubleTime = profiler.End();#ifdef DOUBLE_FIRSTgoto floattest;#endifresults:#ifdef _DEBUGputs("Running in Debug Mode.\n");#endif#ifdef DOUBLE_FIRSTputs("Testing double first, then float.\n");#elseputs("Testing float first, then double.\n");#endif_ASSERT(dFloatTime >= 0.0);_ASSERT(dDoubleTime >= 0.0);printf("float test:  %.3f seconds (%.2f milliseconds, %.1f nanoseconds)\n"   "double test: %.3f seconds (%.2f milliseconds, %.1f nanoseconds)\n\n",   dFloatTime, dFloatTime * 1000.0, dFloatTime * 1000000000.0,   dDoubleTime, dDoubleTime * 1000.0, dDoubleTime * 1000000000.0);if(dFloatTime > dDoubleTime){printf("float was %.2f times (%.1f%%) faster than double.\n\n",dFloatTime / dDoubleTime, dFloatTime / dDoubleTime * 100.0);}else if(dFloatTime < dDoubleTime){printf("double was %.2f times (%.1f%%) faster than float.\n\n",dDoubleTime / dFloatTime, dDoubleTime / dFloatTime * 100.0);}return 0;}