[ECOS] nc_test_slave.c fix
Hugo 'NOx' Tyson
hmt@cygnus.co.ukx
Thu Apr 13 04:30:00 GMT 2000
I had to fiddle with this further for a paricularly fast platform.
The previous version from Grant (thanks Dude!) starts with a high bound and
a low bound and binary chops its way to the correct answer.
But if the high bound is not high enough, it stops *without placing enough
load on the machine*.
The solution is an initial doubling loop that scales up the high load (and
coincidentally replaces the low load with a higher, but known low load) if
that's necessary to bracket the desired load. That loop will execute once
and make no change to the params if the initial high is indeed high enough.
It also features a post scaling to get that last leetle bit closer; for
example, if our measured load is 52% and we want 50%, 50*load/52 has to be
a better estimate. And it is.
Here's the new calibrate_load() routine.
- Huge
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static void
calibrate_load(int desired_load)
{
long long no_load_idle, load_idle;
int percent_load;
int high, low;
// Set limits
high = MAX_LOAD_THREAD_LEVEL;
low = MIN_LOAD_THREAD_LEVEL;
// Compute the "no load" idle value
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
no_load_idle = idle_thread_count;
diag_printf("No load = %d\n", (int)idle_thread_count);
// First ensure that the HIGH level is indeed higher
while (true) {
load_thread_level = high;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("High Load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
if ( percent_load > desired_load )
break; // HIGH level is indeed higher
low = load_thread_level; // known to be lower
high *= 2; // else double it and try again
}
// Now chop down to the level required
while (true) {
load_thread_level = (high + low) / 2;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("Load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
if (((high-low) <= 1) || (abs(desired_load-percent_load) <= 2)) break;
if (percent_load < desired_load) {
low = load_thread_level;
} else {
high = load_thread_level;
}
}
// Now we are within a few percent of the target; scale the load
// factor to get a better fit, and test it, print the answer.
load_thread_level *= desired_load;
load_thread_level /= percent_load;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("Final load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
// no_load_idle_count_1_second = no_load_idle;
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
More information about the Ecos-discuss
mailing list