Subject: [linux-power-mgmt] [PATCH 1/3] cpufreq: intel_pstate: Use avg_pstate instead of current_pstate
From: Philippe Longepe <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]
Date: Mon, 11 Jan 2016 15:29:02 +0100
List-Id: <linux-power-mgmt.eclists.intel.com>

The number of pstates computed by pid_calc was applied to the
current_pstate which is the last requested pstate during the last
period. However, the real pstate can be completely different
(generally higher) because of the frequency sharing per module.

I observed some performance and power impacts during thread
migrations: For example when there is a load of 100% on cpu0 and
5% on cpu1, the current pstate was turbo_pstate on cpu0 and it was
LFM on cpu1, but the real pstate was also turbo on cpu1 in case
they are in the same module. If the main thread migrates from cpu0
to cpu1, the load becomes high on cpu1 and it will take several
periods before we reach again turbo.

Using the average pstate instead of current pstate solve this issue.

Also I moved the intel_pstate_calc_busy function because it was used
only for the performance algorithm.

Performance and power comparison with this patch on Android:

IPLoad+Avg-Pstate vs IP Load:

Benchmark               ∆Perf    ∆Power
SmartBench-Gaming       -0.1%   -10.4%
SmartBench-Productivity -0.8%   -10.4%
CandyCrush                n/a   -17.4%
AngryBirds                n/a    -5.9%
videoPlayback             n/a   -13.9%
audioPlayback             n/a    -4.9%
IcyRocks-0-0             0.0%    -4.0%
IcyRocks-20-50           0.0%   -38.4%
IcyRocks-40-100          0.1%    -2.8%
IcyRocks-60-150          1.4%    -0.6%
IcyRocks-80-200          2.9%     0.7%
IcyRocks-100-250         1.1%     0.4%
iozone RR               -2.7%    -4.2%
iozone RW               -8.8%    -4.2%
Drystone                -0.2%    -0.8%
Coremark                 0.5%     0.2%

Signed-off-by: Philippe Longepe <[email-masked]>
---
 drivers/cpufreq/intel_pstate.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index cd83d47..6ba8cab 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -908,8 +908,6 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
 	cpu->sample.mperf -= cpu->prev_mperf;
 	cpu->sample.tsc -= cpu->prev_tsc;
 
-	intel_pstate_calc_busy(cpu);
-
 	cpu->prev_aperf = aperf;
 	cpu->prev_mperf = mperf;
 	cpu->prev_tsc = tsc;
@@ -931,6 +929,12 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 	mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
+static inline int32_t get_avg_pstate(struct cpudata *cpu)
+{
+	return div64_u64(cpu->pstate.max_pstate * cpu->sample.aperf,
+		cpu->sample.mperf);
+}
+
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 {
 	struct sample *sample = &cpu->sample;
@@ -964,7 +968,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 	cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
 	cpu->sample.busy_scaled = cpu_load;
 
-	return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load);
+	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load);
 }
 
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
@@ -973,6 +977,7 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
 	s64 duration_us;
 	u32 sample_time;
 
+	intel_pstate_calc_busy(cpu);
 	/*
 	 * core_busy is the ratio of actual performance to max
 	 * max_pstate is the max non turbo pstate available
-- 
1.9.1

-------------------------------------
[email-masked]
https://eclists.intel.com/sympa/info/linux-power-mgmt
Unsubscribe by sending email to [email-masked] with subject "Unsubscribe linux-power-mgmt"