sched/fair: optimize find_energy_efficient_cpu() for EAS scheduler

When EAS can not find a best_energy_cpu, consider a idlest cpu as
a backup if it is a little power increased(<3.1%).

Test NenaMark2.apk on RK3588 EVB1 board:
without this patch: min-fps=57, avg-fps=59.4
with this patch:    min-fps=60, avg-fps=60

Change-Id: Ibc99282c21fa32cbed1d4f5dcc66c76a6b120b70
Signed-off-by: Liang Chen <cl@rock-chips.com>
This commit is contained in:
Liang Chen
2022-11-02 17:36:33 +08:00
committed by Tao Huang
parent 57dcba155e
commit bba1b62967

View File

@@ -6681,6 +6681,7 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sync)
{
unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX;
unsigned long best_delta2 = ULONG_MAX;
struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
int max_spare_cap_cpu_ls = prev_cpu, best_idle_cpu = -1;
unsigned long max_spare_cap_ls = 0, target_cap;
@@ -6777,8 +6778,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy
max_spare_cap_cpu = cpu;
}
if (!latency_sensitive)
continue;
if (!IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
if (!latency_sensitive)
continue;
}
if (idle_cpu(cpu)) {
cpu_cap = capacity_orig_of(cpu);
@@ -6795,9 +6798,19 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy
min_exit_lat = idle->exit_latency;
target_cap = cpu_cap;
best_idle_cpu = cpu;
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
best_delta2 = compute_energy(p, cpu, pd);
best_delta2 -= base_energy_pd;
}
} else if (spare_cap > max_spare_cap_ls) {
max_spare_cap_ls = spare_cap;
max_spare_cap_cpu_ls = cpu;
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
if (best_idle_cpu == -1) {
best_delta2 = compute_energy(p, cpu, pd);
best_delta2 -= base_energy_pd;
}
}
}
}
@@ -6825,26 +6838,33 @@ unlock:
if (prev_delta == ULONG_MAX)
return best_energy_cpu;
/*
* when select ROCKCHIP_PERFORMANCE_LOW:
* Pick best_energy_cpu immediately if prev_cpu is big cpu and
* best_energy_cpu is little cpu, so that tasks can migrate from
* big cpu to little cpu easier to save power.
*/
if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
return best_energy_cpu;
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
struct cpumask *cpul_mask = rockchip_perf_get_cpul_mask();
struct cpumask *cpub_mask = rockchip_perf_get_cpub_mask();
int level = rockchip_perf_get_level();
/*
* when select ROCKCHIP_PERFORMANCE_LOW:
* Pick best_energy_cpu if prev_cpu is big cpu and best_energy_cpu
* is little cpu, so that tasks can migrate from big cpu to little
* cpu easier to save power.
*/
if ((level == ROCKCHIP_PERFORMANCE_LOW) && cpul_mask &&
cpub_mask && cpumask_test_cpu(prev_cpu, cpub_mask) &&
cpumask_test_cpu(best_energy_cpu, cpul_mask)) {
return best_energy_cpu;
}
}
if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
return best_energy_cpu;
/*
* Pick the idlest cpu if it is a little power increased(<3.1%).
*/
if ((best_delta2 <= prev_delta) ||
((best_delta2 - prev_delta) < ((prev_delta + base_energy) >> 5)))
return best_idle_cpu >= 0 ? best_idle_cpu : max_spare_cap_cpu_ls;
}
return prev_cpu;