aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorStratos Karafotis <stratosk@semaphore.gr>2013-06-05 12:01:25 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-25 19:06:43 -0400
commitdfa5bb622555d9da0df21b50f46ebdeef390041b (patch)
tree0921347564271c5b89a76721df017abfafe96de7 /drivers/cpufreq
parent3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b (diff)
cpufreq: ondemand: Change the calculation of target frequency
The ondemand governor calculates load in terms of frequency and increases it only if load_freq is greater than up_threshold multiplied by the current or average frequency. This appears to produce oscillations of frequency between min and max because, for example, a relatively small load can easily saturate minimum frequency and lead the CPU to the max. Then, it will decrease back to the min due to small load_freq. Change the calculation method of load and target frequency on the basis of the following two observations: - Load computation should not depend on the current or average measured frequency. For example, absolute load of 80% at 100MHz is not necessarily equivalent to 8% at 1000MHz in the next sampling interval. - It should be possible to increase the target frequency to any value present in the frequency table proportional to the absolute load, rather than to the max only, so that: Target frequency = C * load where we take C = policy->cpuinfo.max_freq / 100. Tested on Intel i7-3770 CPU @ 3.40GHz and on Quad core 1500MHz Krait. Phoronix benchmark of Linux Kernel Compilation 3.1 test shows an increase ~1.5% in performance. cpufreq_stats (time_in_state) shows that middle frequencies are used more, with this patch. Highest and lowest frequencies were used less by ~9%. [rjw: We have run multiple other tests on kernels with this change applied and in the vast majority of cases it turns out that the resulting performance improvement also leads to reduced consumption of energy. The change is additionally justified by the overall simplification of the code in question.] Signed-off-by: Stratos Karafotis <stratosk@semaphore.gr> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_governor.c10
-rw-r--r--drivers/cpufreq/cpufreq_governor.h1
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c39
3 files changed, 8 insertions, 42 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 7b839a8db2a7..7409dbd1d897 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -53,7 +53,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
53 53
54 policy = cdbs->cur_policy; 54 policy = cdbs->cur_policy;
55 55
56 /* Get Absolute Load (in terms of freq for ondemand gov) */ 56 /* Get Absolute Load */
57 for_each_cpu(j, policy->cpus) { 57 for_each_cpu(j, policy->cpus) {
58 struct cpu_dbs_common_info *j_cdbs; 58 struct cpu_dbs_common_info *j_cdbs;
59 u64 cur_wall_time, cur_idle_time; 59 u64 cur_wall_time, cur_idle_time;
@@ -104,14 +104,6 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
104 104
105 load = 100 * (wall_time - idle_time) / wall_time; 105 load = 100 * (wall_time - idle_time) / wall_time;
106 106
107 if (dbs_data->cdata->governor == GOV_ONDEMAND) {
108 int freq_avg = __cpufreq_driver_getavg(policy, j);
109 if (freq_avg <= 0)
110 freq_avg = policy->cur;
111
112 load *= freq_avg;
113 }
114
115 if (load > max_load) 107 if (load > max_load)
116 max_load = load; 108 max_load = load;
117 } 109 }
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 6663ec3b3056..0e0dd4c82020 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -169,7 +169,6 @@ struct od_dbs_tuners {
169 unsigned int sampling_rate; 169 unsigned int sampling_rate;
170 unsigned int sampling_down_factor; 170 unsigned int sampling_down_factor;
171 unsigned int up_threshold; 171 unsigned int up_threshold;
172 unsigned int adj_up_threshold;
173 unsigned int powersave_bias; 172 unsigned int powersave_bias;
174 unsigned int io_is_busy; 173 unsigned int io_is_busy;
175}; 174};
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 93eb5cbcc1f6..a3c5574f9b3a 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -29,11 +29,9 @@
29#include "cpufreq_governor.h" 29#include "cpufreq_governor.h"
30 30
31/* On-demand governor macros */ 31/* On-demand governor macros */
32#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10)
33#define DEF_FREQUENCY_UP_THRESHOLD (80) 32#define DEF_FREQUENCY_UP_THRESHOLD (80)
34#define DEF_SAMPLING_DOWN_FACTOR (1) 33#define DEF_SAMPLING_DOWN_FACTOR (1)
35#define MAX_SAMPLING_DOWN_FACTOR (100000) 34#define MAX_SAMPLING_DOWN_FACTOR (100000)
36#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3)
37#define MICRO_FREQUENCY_UP_THRESHOLD (95) 35#define MICRO_FREQUENCY_UP_THRESHOLD (95)
38#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) 36#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
39#define MIN_FREQUENCY_UP_THRESHOLD (11) 37#define MIN_FREQUENCY_UP_THRESHOLD (11)
@@ -161,14 +159,10 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
161 159
162/* 160/*
163 * Every sampling_rate, we check, if current idle time is less than 20% 161 * Every sampling_rate, we check, if current idle time is less than 20%
164 * (default), then we try to increase frequency. Every sampling_rate, we look 162 * (default), then we try to increase frequency. Else, we adjust the frequency
165 * for the lowest frequency which can sustain the load while keeping idle time 163 * proportional to load.
166 * over 30%. If such a frequency exist, we try to decrease to this frequency.
167 *
168 * Any frequency increase takes it to the maximum frequency. Frequency reduction
169 * happens at minimum steps of 5% (default) of current frequency
170 */ 164 */
171static void od_check_cpu(int cpu, unsigned int load_freq) 165static void od_check_cpu(int cpu, unsigned int load)
172{ 166{
173 struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); 167 struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
174 struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; 168 struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
@@ -178,29 +172,17 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
178 dbs_info->freq_lo = 0; 172 dbs_info->freq_lo = 0;
179 173
180 /* Check for frequency increase */ 174 /* Check for frequency increase */
181 if (load_freq > od_tuners->up_threshold * policy->cur) { 175 if (load > od_tuners->up_threshold) {
182 /* If switching to max speed, apply sampling_down_factor */ 176 /* If switching to max speed, apply sampling_down_factor */
183 if (policy->cur < policy->max) 177 if (policy->cur < policy->max)
184 dbs_info->rate_mult = 178 dbs_info->rate_mult =
185 od_tuners->sampling_down_factor; 179 od_tuners->sampling_down_factor;
186 dbs_freq_increase(policy, policy->max); 180 dbs_freq_increase(policy, policy->max);
187 return; 181 return;
188 } 182 } else {
189 183 /* Calculate the next frequency proportional to load */
190 /* Check for frequency decrease */
191 /* if we cannot reduce the frequency anymore, break out early */
192 if (policy->cur == policy->min)
193 return;
194
195 /*
196 * The optimal frequency is the frequency that is the lowest that can
197 * support the current CPU usage without triggering the up policy. To be
198 * safe, we focus 10 points under the threshold.
199 */
200 if (load_freq < od_tuners->adj_up_threshold
201 * policy->cur) {
202 unsigned int freq_next; 184 unsigned int freq_next;
203 freq_next = load_freq / od_tuners->adj_up_threshold; 185 freq_next = load * policy->cpuinfo.max_freq / 100;
204 186
205 /* No longer fully busy, reset rate_mult */ 187 /* No longer fully busy, reset rate_mult */
206 dbs_info->rate_mult = 1; 188 dbs_info->rate_mult = 1;
@@ -374,9 +356,6 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
374 input < MIN_FREQUENCY_UP_THRESHOLD) { 356 input < MIN_FREQUENCY_UP_THRESHOLD) {
375 return -EINVAL; 357 return -EINVAL;
376 } 358 }
377 /* Calculate the new adj_up_threshold */
378 od_tuners->adj_up_threshold += input;
379 od_tuners->adj_up_threshold -= od_tuners->up_threshold;
380 359
381 od_tuners->up_threshold = input; 360 od_tuners->up_threshold = input;
382 return count; 361 return count;
@@ -525,8 +504,6 @@ static int od_init(struct dbs_data *dbs_data)
525 if (idle_time != -1ULL) { 504 if (idle_time != -1ULL) {
526 /* Idle micro accounting is supported. Use finer thresholds */ 505 /* Idle micro accounting is supported. Use finer thresholds */
527 tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; 506 tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
528 tuners->adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD -
529 MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
530 /* 507 /*
531 * In nohz/micro accounting case we set the minimum frequency 508 * In nohz/micro accounting case we set the minimum frequency
532 * not depending on HZ, but fixed (very low). The deferred 509 * not depending on HZ, but fixed (very low). The deferred
@@ -535,8 +512,6 @@ static int od_init(struct dbs_data *dbs_data)
535 dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; 512 dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
536 } else { 513 } else {
537 tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; 514 tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
538 tuners->adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD -
539 DEF_FREQUENCY_DOWN_DIFFERENTIAL;
540 515
541 /* For correct statistics, we need 10 ticks for each measure */ 516 /* For correct statistics, we need 10 ticks for each measure */
542 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * 517 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *