I wanted to test the difference on modern hardware between floating point match and integer math. Here is my code (which was similar to C# code previously written).
// CSpeedTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include #include using namespace std; #define FP_MULT //#define FP_NEG //#define INT_MULT //#define INT_NEG class StopWatch { LARGE_INTEGER m_freq; LARGE_INTEGER m_startTime; LONGLONG m_totalTime; public: StopWatch() : m_totalTime(0L) { QueryPerformanceFrequency(&m_freq); } void Start() { QueryPerformanceCounter(&m_startTime); } void Stop() { LARGE_INTEGER stopTime; QueryPerformanceCounter(&stopTime); m_totalTime += (stopTime.QuadPart - m_startTime.QuadPart); } void Reset() { m_totalTime = 0L; } double ElapsedTime() { return (double)(m_totalTime) / (double)(m_freq.QuadPart); } }; int _tmain(int argc, _TCHAR* argv[]) { #if defined(FP_MULT) || defined(FP_NEG) volatile double poo = 0.0; #endif #if defined(INT_MULT) || defined(INT_NEG) volatile int poo = 0; #endif StopWatch stopWatch; for (int idx = 0; idx < 1000000000; idx++) { stopWatch.Start(); #if defined(FP_MULT) poo = -1.0 * poo; #endif #if defined(FP_NEG) || defined(INT_NEG) poo = -poo; #endif #if defined(INT_MULT) poo = -1 * poo; #endif stopWatch.Stop(); } double elapsedTime = stopWatch.ElapsedTime(); int minutes = elapsedTime / 60; int seconds = (int) (elapsedTime) % 60; int ms10 = (elapsedTime - int(elapsedTime)) * 100; cout << setfill('0') << setw(2) << minutes << ':' << seconds << ':' << ms10 << endl;; return 0; }
The code was compiled as a console application for Win32 Debug so the variables would get “registered”.
The test machine is a Dell Precision M4800. The process is an Intel Core i7-4800MQ CPU at 2.70 GHz with 16GB ram. The OS is Windows 7 Professional 64 bit with SP1.
Here is the results. I have also included the assembler for the operation under test.
define | time | assembly |
---|---|---|
FP_MULT | 7.32s | fld qword ptr [__real@bff0000000000000 (0BE7938h)]; fmul qword ptr [poo]; fstp qword ptr [poo] |
FP_NEG | 7.56s | fld qword ptr [poo]; fchs; fstp qword ptr [poo] |
INT_MULT | 7.58s | mov eax,dword ptr [poo]; imul eax,eax,0FFFFFFFFh; mov dword ptr [poo],eax |
INT_NEG | 7.59s | mov eax,dword ptr [poo]; neg eax; mov dword ptr [poo],eax |
I actually don’t believe I have accomplished too much as the setup to call the timing functions actually take many, many more opcodes. However, this was an interesting experiment and I do now have a cool C++ stopwatch on Windows for more extensive testing on much larger blocks of test code.