Problem Statement: High CPU clock speed/freq
Requirement: Obtain a stable CPU clock ticks/speed/freq on Suse 11.1 with kernel 2.6.27.7-9
Questions: Please refer to the bottom of this page
Artifacts in Use:
-----------------------------------
OS: Suse 11.1
GCC Version: 4.3.2 (Suse Linux) [gcc_4_3-brach revision 141291]
Kernel: 2.6.27.7-9
Kernel Mods:
* Un-check the Tickless option
* Timer Frequency - 1000Hz
* Preempt kernel
Others 1
-----------
OS: Suse 10.2
GCC Version: 4.1.2 20061115 (prerelease)(SUSE Linux)
Kernel: 2.6.18.2-34-default
Kernel Mods:
* Preemptible Kernel (Low-Latency Desktop) (NEW)
* Preempt The Big Kernel Lock (NEW)
* Timer frequency (NEW) - 1000 Hz (NEW)
Others 2
-----------
OS: Suse 9.3
GCC Version: 3.3.5 20050117 (prerelease)(SUSE Linux)
Kernel 2.6.11.4-20a-default
Kernel Mods: None
I executed the following c++ code on the above stated builds
CODE - file name test.cpp
<code>
Code:
#include <signal.h>
#include <sys/time.h>
#include <iostream>
#include <cstdlib>
using namespace std;
long long int counter = 0;
struct timeval last_time;
struct timeval curr_time;
double dif = 0.0;
double freq_sum = 0.0;
double reps = 0.0;
double freq_min = 99999.0;
double freq_max = 0.0;
long long int num_too_low = 0;
void time_check(int data)
{
// work out the frequecy of the SIGALRMs
++counter;
if (counter >= 1000)
{
// need to work out time since last 1000 ticks
gettimeofday(&curr_time, NULL);
dif = ((curr_time.tv_usec + curr_time.tv_sec * 1000000)
- (last_time.tv_usec + last_time.tv_sec * 1000000));
double freq = (counter / dif) * 1000000;
freq_sum = ((freq_sum * reps) + freq) / (reps + 1) ;
++reps;
cout << "Frequency = " << freq << " reps= " << dif / 1000000 << endl;
if (freq_min > freq) freq_min = freq;
if (freq_max < freq) freq_max = freq;
if (freq < 950)
++num_too_low;
last_time = curr_time;
counter = 0;
}
}
int main (int argc, char * argv[])
{
cout << "go" /* << "\a \a \a" */ << endl;
int res;
gettimeofday(&last_time, NULL);
struct sigaction action;
struct itimerval timer_value;
timer_value.it_value.tv_sec = 0;
timer_value.it_value.tv_usec = 1;
timer_value.it_interval.tv_sec = 0;
timer_value.it_interval.tv_usec = 1;
action.sa_handler = time_check;
action.sa_flags = SA_NOMASK;
sigemptyset(&action.sa_mask);
sigaction( SIGALRM, &action, NULL);
res = setitimer( ITIMER_REAL, &timer_value, NULL );
if (res == -1)
cout << "error in setitimer" << endl;
cout << "Starting CPU Test program" << endl;
// loop for a long time
while (reps < 3000.0)
{
sleep(1);
}
cout << "average CPU frequency = " << freq_sum << endl;
cout << "reps = " << reps << endl;
cout << "Min = " << freq_min << " Max = " << freq_max << endl;
cout << "number of low = " << num_too_low << endl;
return 0;
}
Compiled the above code with "g++ test.cpp -o test"
Run the above code with "./test"
Observations:
SUSE Version AVG. Frequency AVG. REPS
Suse 9.3 999.xxx to 990.xxx reps > 1 (on average)
Suse 10.2 999.xxx to 998.xxx reps (1 - 1.001)
Suse 10.3 1000.xxx to 912.xxx reps (1 - 1.090)
Suse 11.1 0 to 324263.xxx reps (-2e-0.6 upto 0.005112)
Suse 11.1 - Options:
- Turn off ACPI in options when booting with clock=tsc | clock=pit
Observations for suse 11.1 with options acpi=off and clock=tsc | clock=pit
SUSE Version AVG. Frequency AVG. REPS
Suse 11.1 710.xxx to 999.xxx reps (1.37xx to 1.0002)
Hardware used for Suse 11.1 - HP Pavilion Slimline s3821uk Desktop PC (NQ808AA) specifications - HP Home & Home Office products
http://h10010.www1.hp.com/wwpc/uk/en...t-xx-xx-/chev/
While testing no other application/s were running.
Question:
* Is my c++ code correct?
* Am I using the correct way to get the clock ticks or is there more reliable tchnique avaliable to do this?
* Is that a problem with new Kernel if so is it a known issue ?
* Do I need to modify the Kernel to obtain regular and stable clock tick at 1000 Hz ?
* Do I have to upgrade the Kernel ?
* Would be great, if pointed to the right direction for solution (e.g. another forum) if no solution at hand.
Thanks