Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1432
  • Last Modified:

how to measure cpu time cpp

how to measure cpu time cpp
05/18/09 - added C++ zone - Callandor

Open in new window

0
kalech
Asked:
kalech
  • 4
  • 2
  • 2
  • +4
1 Solution
 
kalechAuthor Commented:
I try to measure the cpu time of an exponential function in Cpp in Windows XP. It is important for me to measure only the function time ignoring the I/O time and ignoring other processes. I am looking for an API that I can use start and end, and it measure the cpu between them so I acan measure only the cpu time of the function.
0
 
CallandorCommented:
You may want to use the clock() function - see http://www.physicsforums.com/showthread.php?t=224989
0
 
DevoneyCommented:
I think you want to use the 'rdtsc' instruction (0x0F31). This will fill EAX:EDX with a 64 bit value specifying the current clock cycle. If you request it twice and extract these values you have the difference in clock cycles that was needed to perform the operation between your timepoints.

You could also use DWORD WINAPI GetTickCount(void); which returns the miliseconds since system startup, you could use this to for timing an operation.

The best way to go is executing your exponential function before windows has booted. Or in a virtual machine (VmWare). I have experienced that timings in a virtual machine are not effected by other processes in the windows host (handy for quickly testing). So compile your code with the timing of your choice in a console mode application and run that by using a bootdisk of somekind (floppy, virtual floppy, CD-ROM). Otherwise you will never know how many CPU clocks where spent on other processes running in the background. Example in assembly about RDTSC I have once written is included.

// CPUSpeed.cpp : Defines the entry point for the console application.
#include <stdafx.h>
#include <iostream>
#include <string>
#include <Windows.h>
#include <stdio.h>
#include <winbase.h>
#include <winuser.h>
 
using namespace std;
 
int _tmain(int argc, _TCHAR* argv[])
{
	system("cls"); //Clean the console screen
	SetConsoleTitleA("CPU Current Working Speed - by Devoney"); //Set the title of the console screen
	__int64 Answer = 0; //Make a 64-bit, way to large, variable.
 
	//Output some text describing the program and offering the user to choose the time interval.
	cout << "CPU Current Working Speed\n\nThis program will measure how many clockcycles have passed during a time interval. Then it will calculate how many clockcycles this have been per second and convert the value in Mhz. The program will NOT measure the speed of the CPU in Ghz at which is clocked on, but will measure it's current working speed while executing this program.\n\n";
	cout << "Select your time interval: \n1. 1sec\n2. 2sec\n3. 5sec\n4. 10sec\n5. 30sec\n\nAnswer: ";
	
	cin >> Answer; //retrieve answer
 
	//Check which answer was given and redefine Answer for later use in the Sleep() function.
	//Notice that their is no error handler when wrong input is given.
	if(Answer == 1)
	{
		Answer = 1000;
	}
	if(Answer == 2)
	{
		Answer = 2000;
	}
		if(Answer == 3)
	{
		Answer = 5000;
	}
	if(Answer == 4)
	{
		Answer = 10000;
	}
	if(Answer == 5)
	{
		Answer = 30000;
	}
 
	//Initialize 3 64-bit variables, the returned value of RDTSC is 64 bit. We need to obtain it twice and substract them.
	__int64 unsigned BeginClock = 0;
	__int64 unsigned EndClock = 0;
	__int64 unsigned Speed = 0;
	cout << "\nVariables initialized...\n";
	
	//Try to set the priority of the program to the highest possible, realtime.
	if(SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS))
	{
		cout << "Priority Class Set To Realtime...\n";
	}
	else
	{
		cout << "Priority Class Could Not Be Set To Realtime...\n";
	}
 
	cout << "Waiting for interval to pass...\n\n";
	_asm
	{
		RDTSC //Execute the opcode RDTSC
		mov DWORD PTR SS:[BeginClock], EAX //Move the bytes stored in EAX to the variable BeginClock
		mov DWORD PTR SS:[BeginClock+4], EDX //Move the most significant bytes stored in EDX to BeginClock
	}
	
		Sleep(Answer); //Wait the chosen amount of time
 
	_asm
	{
		//Again use RDTSC
		RDTSC
		mov DWORD PTR SS:[EndClock], EAX
		mov DWORD PTR SS:[EndClock+4], EDX
	}
 
 
	Speed  = (EndClock - BeginClock); //Substract the two RDTSC values to obtain the clockcycles done in the time interval
	cout << "Clockcycles since reset (before interval): " << BeginClock << "\nClockcycles since reset (after interval):  " << EndClock << "\nAmount of Clockcycles after substraction:  " << Speed << "\n";
	Speed = Speed / (1000000 * (Answer/1000)); //Convert the clockcycles to Mhz using the time interval and 1,000,000 constant because otherwise the speed is given in Hz
	cout << "Measured CPU Speed: " << Speed << "Mhz\nProgram Terminated\n";
	return 0; //Exit the program
}

Open in new window

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
DevoneyCommented:
The example code is VS2005 ;) Is their an option to edit a comment?
0
 
jkrCommented:
'clock()' won't help much, since it does only yield a time difference, not the time a process has been utilizing the CPU during that period. 'GetProcessTimes()' (http://msdn.microsoft.com/en-us/library/ms683223.aspx) would be more what yopu want. By adding *lpKernelTime and *lpUserTime spent between two consecutive calls, you'll get the effective CPU time used for that process, e.g.
#define FT2INT64(x) (*(( _int64*)&x))
 
FILETIME ftKernel1, ftKernel2;
FILETIME ftUser1, ftUser2;
FILETIME ftCreate, ftExit;
 
GetProcessTimes(&ftCreation,&ftExit,&ftKernel1,&ftUser1);
 
// run your exponential function here
 
GetProcessTimes(&ftCreation,&ftExit,&ftKernel2,&ftUser2);
 
__int64 lnTimeSpentUser = FT2INT64(ftUser2) - FT2INT64(ftUser1);
__int64 lnTimeSpentKernel = FT2INT64(ftKernel2) - FT2INT64(ftKernel1);
 
__int64 lnTimeSpentTotal = lnTimeSpentUser + lnTimeSpentKernel;
 
// result is in nanoseconds, see http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx

Open in new window

0
 
JIEXACommented:
jkr,
'clock()' is told to measure CPU time, this is what is written in manuals. Is this wrong for Windows???
0
 
AkumasCommented:
well,I had the same requirement to test my public lib's performance
here's my solution,just pseudocode, hope helpfull
it's really hard to remember exactly code:)

//class to statistic
class statistic
{
 static void record(const string& func_name, const long& elased_tickets)
  {
    //record and statistic cpu time for each function
  }
}

//class to record time
class caculator
{
  long begin_time;
  string name;
  caculator(const string& func_name)
  {
    name = func_name;
    begin_time = getTicketCount();
  }
  ~caculator()
  {
    long elapsed = getTicketCount() - begin_time;
    //record&statistic
    statistic::record(name, elapsed);
  }
}

usage:
void my_method1(xxx)
{
  caculator m("method1");
  //do somthing
}
void my_method2(xxx)
{
  caculator m("method2");
  //do somthing
}

you can measure different functions at same time, I like this very much:)

remember,getTicketCount is not fully reliable,it will reset after time,you should protect this situation or try other system function.
0
 
adg080898Commented:
To measure cpu time in Win32, use GetThreadTimes.

http://msdn.microsoft.com/en-us/library/ms683237.aspx

It returns the amount of user mode cpu time, kernel mode cpu time, thread creation time, and thread exit time...

FILETIME is simply a 64 bit value where 1 = 100 nanoseconds. 10000 = 1 millisecond. However, FILETIME is a (silly) structure that contains two 32-bit values that make up a 64 bit value.

I have used a union to allow you to nicely read the whole 64 bit value.

#include <windows.h>
#include <tchar.h>
#include <math.h>
 
union WrapFiletime
{
    FILETIME ft;
    __int64 value;
};
 
volatile double dummy;
void DoSomething()
{
    for (int i = 0; i < 200000000; ++i)
    {
        dummy = sqrt((double)i);
    }
}
 
void TimeSomething()
{
    WrapFiletime creationTime;
    WrapFiletime exitTime;
    WrapFiletime kernelTime;
    WrapFiletime userTime;
    GetThreadTimes(GetCurrentThread(), 
            &creationTime.ft, &exitTime.ft, 
            &kernelTime.ft, &userTime.ft);
 
    __int64 startKernelTime = kernelTime.value;
    __int64 startUserTime = userTime.value;
 
    // ..... DO SOMETHING .....
    DoSomething();
    // ..... DO SOMETHING .....
 
    GetThreadTimes(GetCurrentThread(), 
            &creationTime.ft, &exitTime.ft, 
            &kernelTime.ft, &userTime.ft);
 
    __int64 endKernelTime = kernelTime.value;
    __int64 endUserTime = userTime.value;
 
    _tprintf(_T("CPU time: kernel=%dms, user=%dms\n"),
            (int)((endKernelTime-startKernelTime)/10000),
            (int)((endUserTime-startUserTime)/10000));
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    TimeSomething();
    return 0;
}

Open in new window

0
 
adg080898Commented:
Devoney:
there is an intrinsic function __rdtsc() that always works on x86 (even on 64bit platform). But that doesn't answer his question, he wanted to factor out I/O time and time taken by other running programs, and just measure the cpu time consumed by his exponential function.

jkr:
just noticed the GetProcessTimes respose :) That is similar to my response, but it measures the time taken by all threads in the process. Mostly equivalent in a single thread scenario, assuming none if his libraries are creating worker threads and he's not using the system thread pool, etc.
0
 
adg080898Commented:
I don't see why jkr's answer deserves 100% of the points. I posted a complete, runnable example that measures the time consumed in a thread, not the entire process.
0
 
jkrCommented:
Um:

- I don't see that more than one thread was involved in that Q.
- you posted two weeks(!) later, where that question was already close to abandoned. I doubt that this was the intention of the asker - to wait for two weeks... "just noticed the GetProcessTimes respose" indicates that you're not really reading threads before posting, which is not something that is customary at this site... especially since you had a whopping two weeks to do so.
0
 
adg080898Commented:
I don't need to be disrespected for donating time to a commercial site. I'm not sure why I'm wasting my time posting responses in here anyway.
0
 
JIEXACommented:
The first sentence of the accepted solution is wrong.
0
 
CallandorCommented:
Yes, the last comment in the link I posted says "clock() doesn't necessarily have anything to do with time as measured by the clock on the wall -- it measures the time used by your process."
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 4
  • 2
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now