330 lines
6.3 KiB
C++
330 lines
6.3 KiB
C++
// toIntTest.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <limits>
|
|
#include <math.h>
|
|
|
|
#undef min
|
|
#undef max
|
|
|
|
|
|
#if defined( WIN32 )
|
|
//#define QUERY_PERFORMANCE_COUNTER
|
|
#define RDTSC
|
|
#else
|
|
#define GET_TIME_OF_DAY
|
|
#endif
|
|
|
|
#ifdef RDTSC
|
|
#include <windows.h>
|
|
|
|
class perf
|
|
{
|
|
__int64 r64;
|
|
|
|
__forceinline __int64 getCurrentTime()
|
|
{
|
|
__asm
|
|
{
|
|
//
|
|
// Serialized instruction ensure all previouse
|
|
// instructions a done befor reading the performance
|
|
// counter.
|
|
//
|
|
// cpuid
|
|
//
|
|
// Read the time stamp counter.
|
|
//
|
|
rdtsc
|
|
}
|
|
}
|
|
|
|
public:
|
|
__forceinline perf()
|
|
{
|
|
::Sleep( 0 );
|
|
__asm cpuid
|
|
r64 = getCurrentTime();
|
|
}
|
|
|
|
__forceinline double elapsed()
|
|
{
|
|
__int64 now = getCurrentTime();
|
|
return double(now - r64 );
|
|
}
|
|
|
|
};
|
|
|
|
__int64 nCPUFrequency;
|
|
double dblCPUFrequency;
|
|
|
|
inline __int64 getCurrentTimeI()
|
|
{
|
|
__asm
|
|
{
|
|
rdtsc
|
|
}
|
|
}
|
|
|
|
inline double getCurrentTime()
|
|
{
|
|
// return double(getCurrentTimeI());
|
|
//
|
|
// The time stamp counter.
|
|
//
|
|
union {
|
|
__int64 r64;
|
|
__int32 r32[2];
|
|
} tsc;
|
|
//
|
|
// Read the time stamp counter.
|
|
//
|
|
__asm
|
|
{
|
|
//
|
|
// Serialized instruction ensure all previouse
|
|
// instructions a done befor reading the performance
|
|
// counter.
|
|
//
|
|
// cpuid
|
|
//
|
|
// Read the counter.
|
|
//
|
|
rdtsc
|
|
//
|
|
//
|
|
//
|
|
// mov tsc.r32[0], eax
|
|
// mov tsc.r32[4], edx
|
|
movd xmm0,eax
|
|
movd xmm1,edx
|
|
pshufd xmm1, xmm0, 0xF7
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get time in seconds.
|
|
//
|
|
return double(tsc.r64);// / dblCPUFrequency;
|
|
}
|
|
|
|
void initGetCurrentTimeLib_hlpr()
|
|
{
|
|
//
|
|
// Use only one fixed CPU
|
|
//
|
|
BOOL b;
|
|
DWORD_PTR proc_affi;
|
|
DWORD_PTR sys_affi;
|
|
DWORD_PTR exclud_affi;
|
|
GetProcessAffinityMask( GetCurrentProcess(), &proc_affi, &sys_affi );
|
|
exclud_affi = proc_affi & ~sys_affi;
|
|
proc_affi = ( exclud_affi ) ? proc_affi : proc_affi;
|
|
int i = 0;
|
|
while (( proc_affi >>= 1 )) ++i;
|
|
proc_affi = 1 << i;
|
|
b = SetProcessAffinityMask( GetCurrentProcess(), proc_affi );
|
|
//
|
|
// Set the priority of thread high.
|
|
//
|
|
b = SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );
|
|
b = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
|
|
//
|
|
// Get the frequency.
|
|
//
|
|
nCPUFrequency = 2000000000;
|
|
// QueryPerformanceFrequency(
|
|
// reinterpret_cast<LARGE_INTEGER*>( &nCPUFrequency ) );
|
|
//
|
|
// Frequency counter supported in CPUs of family x86
|
|
// starting from Pentium 4 or Pentium 3. So for old CPUs
|
|
// this will not work.
|
|
//
|
|
// If CPU doesn't support performance counter then just return.
|
|
//
|
|
if ( !nCPUFrequency )
|
|
puts("WARNING: This CPU doesn't support QueryPerformanceFrequency.");
|
|
//
|
|
// Convert to double.
|
|
//
|
|
dblCPUFrequency = double(nCPUFrequency);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef QUERY_PERFORMANCE_COUNTER
|
|
#include <windows.h>
|
|
|
|
double dblCPUFrequency;
|
|
inline double getCurrentTime()
|
|
{
|
|
//
|
|
// This call must be quite fast. Since, in x86 architectur
|
|
// it is one instruction. Yet WIN32 API might added some
|
|
// additional processing.
|
|
//
|
|
// \todo Vahagn: add our assembly optimised function.
|
|
//
|
|
__int64 nCPUTickCount;
|
|
QueryPerformanceCounter(
|
|
reinterpret_cast<LARGE_INTEGER*>( &nCPUTickCount )
|
|
);
|
|
//
|
|
// Get time in seconds.
|
|
//
|
|
return double(nCPUTickCount) / dblCPUFrequency;
|
|
}
|
|
|
|
void initGetCurrentTimeLib_hlpr()
|
|
{
|
|
//
|
|
// Use only one fixed CPU
|
|
//
|
|
BOOL b;
|
|
DWORD_PTR proc_affi;
|
|
DWORD_PTR sys_affi;
|
|
DWORD_PTR exclud_affi;
|
|
GetProcessAffinityMask( GetCurrentProcess(), &proc_affi, &sys_affi );
|
|
exclud_affi = proc_affi & ~sys_affi;
|
|
proc_affi = ( exclud_affi ) ? proc_affi : proc_affi;
|
|
int i = 0;
|
|
while (( proc_affi >>= 1 )) ++i;
|
|
proc_affi = 1 << i;
|
|
b = SetProcessAffinityMask( GetCurrentProcess(), proc_affi );
|
|
//
|
|
// Set the priority of thread high.
|
|
//
|
|
b = SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );
|
|
b = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
|
|
//
|
|
// Get the frequency.
|
|
//
|
|
__int64 nCPUFrequency;
|
|
QueryPerformanceFrequency(
|
|
reinterpret_cast<LARGE_INTEGER*>( &nCPUFrequency )
|
|
);
|
|
//
|
|
// Frequency counter supported in CPUs of family x86
|
|
// starting from Pentium 4 or Pentium 3. So for old CPUs
|
|
// this will not work.
|
|
//
|
|
// If CPU doesn't support performance counter then just return.
|
|
//
|
|
if ( !nCPUFrequency )
|
|
puts("WARNING: This CPU doesn't support QueryPerformanceFrequency.");
|
|
//
|
|
// Convert to double.
|
|
//
|
|
dblCPUFrequency = double(nCPUFrequency);
|
|
}
|
|
#endif
|
|
|
|
#ifdef GET_TIME_OF_DAY
|
|
#include <sys/time.h>
|
|
|
|
inline double getCurrentTime()
|
|
{
|
|
timeval t;
|
|
gettimeofday(&t,0);
|
|
return (double)t.tv_sec + ((double)t.tv_usec/1000000.0);
|
|
}
|
|
|
|
void initGetCurrentTimeLib_hlpr()
|
|
{
|
|
}
|
|
|
|
#endif
|
|
|
|
void initGetCurrentTimeLib()
|
|
{
|
|
initGetCurrentTimeLib_hlpr();
|
|
|
|
#if 0
|
|
for ( int j=0; j < 10000; ++j )
|
|
{
|
|
|
|
//
|
|
// Calculate the time expectation and dispersion
|
|
// of getCurrentTime on this CPU.
|
|
//
|
|
const int nProbeCount = 100000;
|
|
double dblTimeExpect = 0.;
|
|
double dblTimeDispersia = 0.;
|
|
for ( int i = nProbeCount; i; --i )
|
|
{
|
|
register double dblTimeBase = getCurrentTime();
|
|
register double dblTimeCurrent = getCurrentTime();
|
|
double dblTimeDelta = dblTimeCurrent - dblTimeBase;
|
|
dblTimeExpect += dblTimeDelta;
|
|
dblTimeDispersia += dblTimeDelta * dblTimeDelta;
|
|
}
|
|
//
|
|
// finalize.
|
|
//
|
|
dblTimeExpect /= double( nProbeCount );
|
|
dblTimeDispersia = dblTimeDispersia / double( nProbeCount )
|
|
- dblTimeExpect * dblTimeExpect;
|
|
printf( "Expectation: %f\n"
|
|
"Dispersion: %f\n",
|
|
dblTimeExpect,
|
|
sqrt(dblTimeDispersia) );
|
|
puts( "----------------------------------------------------" );
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
const int nProbeCount = 1000;
|
|
double* ddd = new double[ nProbeCount ];
|
|
double* p = ddd;
|
|
double m = std::numeric_limits<double>::max();
|
|
for ( int i = nProbeCount; i; --i )
|
|
{
|
|
register double dblTimeBase = getCurrentTime();
|
|
register double dblTimeCurrent = getCurrentTime();
|
|
*p++ = dblTimeCurrent - dblTimeBase;
|
|
m = std::min( m, dblTimeCurrent - dblTimeBase );
|
|
// printf( "%10.1f\n", dblTimeCurrent - dblTimeBase );
|
|
}
|
|
|
|
printf( "%10.1f\n", m );
|
|
|
|
std::ofstream o;
|
|
o.open( "times.txt" );
|
|
p = ddd;
|
|
for ( int i = nProbeCount; i; --i )
|
|
{
|
|
o << *p++ << std::endl;
|
|
}
|
|
o << std::endl;
|
|
delete [] ddd;
|
|
#endif
|
|
|
|
#if 1
|
|
|
|
for ( int j = 0; j < 1000; ++j )
|
|
{
|
|
const int nProbeCount = 10000;
|
|
double m = 1e300;
|
|
for ( int i = nProbeCount; i; --i )
|
|
{
|
|
perf pc;
|
|
__asm cpuid
|
|
__asm cpuid
|
|
__asm cpuid
|
|
__asm cpuid
|
|
double c = pc.elapsed();
|
|
m = min( m, c );
|
|
}
|
|
std::cout << m << std::endl;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|