diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | devices/thinkpad-fan.cpp | 13 | ||||
-rw-r--r-- | main.cpp | 9 | ||||
-rw-r--r-- | parameters/learn.cpp | 87 | ||||
-rw-r--r-- | process/do_process.cpp | 2 |
5 files changed, 83 insertions, 34 deletions
@@ -1,8 +1,8 @@ all: powertop graphparameters -CFLAGS += -Wall -O0 -g -CPPFLAGS += -Wall -O0 -g -CXXFLAGS += -Wall -O0 -g +CFLAGS += -Wall -O2 -g -fno-omit-frame-pointer +CPPFLAGS += -Wall -O2 -g -fno-omit-frame-pointer +CXXFLAGS += -Wall -O2 -g -fno-omit-frame-pointer OBJS := lib.o main.o OBJS += cpu/cpu.o cpu/abstract_cpu.o cpu/cpu_linux.o cpu/cpu_core.o cpu/cpu_package.o cpu/intel_cpus.o cpu/cpudevice.cpp OBJS += perf/perf.o perf/perf_bundle.o diff --git a/devices/thinkpad-fan.cpp b/devices/thinkpad-fan.cpp index 11b7284..286cfe0 100644 --- a/devices/thinkpad-fan.cpp +++ b/devices/thinkpad-fan.cpp @@ -4,6 +4,7 @@ #include <stdio.h> #include <sys/types.h> #include <dirent.h> +#include <math.h> #include "../lib.h" @@ -66,13 +67,21 @@ double thinkpad_fan::power_usage(struct result_bundle *result, struct parameter_ double utilization; power = 0; - factor = get_parameter_value("thinkpad-fan", bundle); utilization = get_result_value("thinkpad-fan", result); utilization = utilization - 50; if (utilization < 0) utilization = 0; - power += utilization * factor / 100.0; + + factor = get_parameter_value("thinkpad-fan-sqr", bundle); + power += factor * pow(utilization / 100.0, 2); + + factor = get_parameter_value("thinkpad-fan", bundle); + power -= utilization * factor / 100.0; + + if (power <= 0.0) + power = 0.0; + return power; } @@ -42,7 +42,7 @@ void one_measurement(int seconds) global_joules_consumed(); compute_bundle(); - report_devices(); +// report_devices(); store_results(); end_cpu_data(); } @@ -85,16 +85,16 @@ int main(int argc, char **argv) - learn_parameters(600); + learn_parameters(50); dump_parameter_bundle(); save_parameters("saved_parameters.powertop"); /* first one is short to not let the user wait too long */ one_measurement(5); - for (i = 0; i < 5; i++) { + for (i = 0; i < 25; i++) { one_measurement(20); - learn_parameters(10); + learn_parameters(15); } @@ -103,6 +103,7 @@ int main(int argc, char **argv) end_cpu_data(); save_all_results("saved_results.powertop"); + save_parameters("saved_parameters.powertop"); learn_parameters(500); save_parameters("saved_parameters.powertop"); printf("Final estimate:\n"); diff --git a/parameters/learn.cpp b/parameters/learn.cpp index f5556e9..e1e248c 100644 --- a/parameters/learn.cpp +++ b/parameters/learn.cpp @@ -35,6 +35,17 @@ static int random_disturb(int retry_left) return 0; } +static int try_zero(double value) +{ + if (value > 0.01) + if ( (rand() % 100) == 1) + return 1; + + if ( (rand() % 5) == 1) + return 1; + return 0; +} + static unsigned int previous_measurements; /* leaks like a sieve */ @@ -44,6 +55,8 @@ void learn_parameters(int iterations, const char *pattern) double best_score = 10000000000000000.0; map<string, double>::iterator it; int retry = iterations; + string prevparam = ""; + int locked = 0; // if (past_results.size() == previous_measurements) // return; @@ -81,46 +94,56 @@ void learn_parameters(int iterations, const char *pattern) while (retry--) { int changed = 0; string bestparam; - double newvalue; + double newvalue = 0; + double orgscore; bestparam = ""; calculate_params(best_so_far); - best_score = best_so_far->score; + orgscore = best_score = best_so_far->score; for (it = best_so_far->parameters.begin(); it != best_so_far->parameters.end(); it++) { double value, orgvalue; + string param; + + param = it->first; if (pattern) { - if (strstr(it->first.c_str(), pattern) != NULL) { + if (strstr(param.c_str(), pattern) != NULL) { continue; } } - orgvalue = value = best_so_far->parameters[it->first]; +// if (locked) { +// param = prevparam; +// if (it != best_so_far->parameters.begin()) +// break; +// } + + orgvalue = value = best_so_far->parameters[param]; if (value <= 0.001) { value = 0.1; } else value = value * (1 + delta); - if (it->first == "base power" && value > min_power) + if (param == "base power" && value > min_power) value = min_power; - if (it->first == "base power" && orgvalue > min_power) + if (param == "base power" && orgvalue > min_power) orgvalue = min_power; if (value > 5000) value = 5000; -// printf("Trying %s %4.2f -> %4.2f\n", it->first.c_str(), best_so_far->parameters[it->first], value); - best_so_far->parameters[it->first] = value; +// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), best_so_far->parameters[param], value); + best_so_far->parameters[param] = value; calculate_params(best_so_far); if (best_so_far->score < best_score || random_disturb(retry)) { best_score = best_so_far->score; newvalue = value; - bestparam = it->first; + bestparam = param; changed++; } @@ -129,42 +152,58 @@ void learn_parameters(int iterations, const char *pattern) if (value < 0.0001) value = 0.0; + if (try_zero(value)) + value = 0.0; + if (value > 5000) value = 5000; -// printf("Trying %s %4.2f -> %4.2f\n", it->first.c_str(), orgvalue, value); - best_so_far->parameters[it->first] = value; +// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), orgvalue, value); - calculate_params(best_so_far); - if (best_so_far->score + 0.00001 < best_score || random_disturb(retry)) { - best_score = best_so_far->score; - newvalue = value; - bestparam = it->first; - changed++; + if (orgvalue != value) { + best_so_far->parameters[param] = value; + + calculate_params(best_so_far); + + if (best_so_far->score + 0.00001 < best_score || (random_disturb(retry) && value > 0.0)) { + best_score = best_so_far->score; + newvalue = value; + bestparam = param; + changed++; + } } - best_so_far->parameters[it->first] = orgvalue; + best_so_far->parameters[param] = orgvalue; } if (!changed) { double mult; - mult = 0.8; - if (iterations < 25) - mult = 0.5; - delta = delta * mult; + + if (!locked) { + mult = 0.8; + if (iterations < 25) + mult = 0.5; + delta = delta * mult; + } + locked = 0; + prevparam = ""; } else { if (debug_learning) { printf("Retry is %i \n", retry); printf("delta is %5.4f\n", delta); printf("Best parameter is %s \n", bestparam.c_str()); - printf("Changing score from %4.3f to %4.3f\n", best_so_far->score, best_score); + printf("Changing score from %4.3f to %4.3f\n", orgscore, best_score); printf("Changing value from %4.3f to %4.3f\n", best_so_far->parameters[bestparam], newvalue); } best_so_far->parameters[bestparam] = newvalue; + if (prevparam == bestparam) + delta = delta * 1.1; + prevparam = bestparam; + locked = 1; } - if (delta < 0.001) + if (delta < 0.001 && !locked) break; } diff --git a/process/do_process.cpp b/process/do_process.cpp index cc178ec..947c53a 100644 --- a/process/do_process.cpp +++ b/process/do_process.cpp @@ -199,7 +199,7 @@ void perf_process_bundle::handle_trace_point(int type, void *trace, int cpu, uin /* start new process */ new_proc->schedule_thread(time, sw->next_pid); - if (strncmp(sw->next_comm,"migration/", 10) && strncmp(sw->next_comm,"kworker/", 8) ) { + if (strncmp(sw->next_comm,"migration/", 10) && strncmp(sw->next_comm,"kworker/", 8) && strncmp(sw->next_comm, "kondemand/",10)) { if (sw->next_pid) { /* If someone woke us up.. blame him instead */ if (new_proc->waker) { |