History

sched/fair: Fix negative energy delta in find_energy_efficient_cpu()

find_energy_efficient_cpu() (feec()) searches the best energy CPU to place a task on. To do so, compute_energy() estimates the energy impact of placing the task on a CPU, based on CPU and task utilization signals. Utilization signals can be concurrently updated while evaluating a performance domain (pd). In some cases, this leads to having a 'negative delta', i.e. placing the task in the pd is seen as an energy gain. Thus, any further energy comparison is biased. In case of a 'negative delta', return prev_cpu since: 1. a 'negative delta' happens in less than 0.5% of feec() calls, on a Juno with 6 CPUs (4 little, 2 big) 2. it is unlikely to have two consecutive 'negative delta' for a task, so if the first call fails, feec() will correctly place the task in the next feec() call 3. EAS current behavior tends to select prev_cpu if the task doesn't raise the OPP of its current pd. prev_cpu is EAS's generic decision 4. prev_cpu should be preferred to returning an error code. In the latter case, select_idle_sibling() would do the placement, selecting a big (and not energy efficient) CPU. As 3., the task would potentially reside on the big CPU for a long time

Pierre Gondois committed 5 years ago

Commit 619e0901 parent 8d4c97c1 file · +15 −12Browse files

Unified · Split

kernel/sched/fair.c+15−12
@@ -6661,15 +6661,15 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) · 6660 unmodified lines
66616661 {
66626662 unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX;
66636663 struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
6664+ int cpu, best_energy_cpu = prev_cpu, target = -1;
66646665 unsigned long cpu_cap, util, base_energy = 0;
6665− int cpu, best_energy_cpu = prev_cpu;
66666666 struct sched_domain *sd;
66676667 struct perf_domain *pd;
66686668
66696669 rcu_read_lock();
66706670 pd = rcu_dereference(rd->pd);
66716671 if (!pd || READ_ONCE(rd->overutilized))
6672− goto fail;
6672+ goto unlock;
66736673
66746674 /*
66756675 * Energy-aware wake-up happens on the lowest sched_domain starting
@@ -6679,7 +6679,9 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) · 3 unmodified lines
66796679 while (sd && !cpumask_test_cpu(prev_cpu, sched_domain_span(sd)))
66806680 sd = sd->parent;
66816681 if (!sd)
6682− goto fail;
6682+ goto unlock;
6683+
6684+ target = prev_cpu;
66836685
66846686 sync_entity_load_avg(&p->se);
66856687 if (!task_util_est(p))
@@ -6734,6 +6736,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) · 48 unmodified lines
67346736 /* Evaluate the energy impact of using prev_cpu. */
67356737 if (compute_prev_delta) {
67366738 prev_delta = compute_energy(p, prev_cpu, pd);
6739+ if (prev_delta < base_energy_pd)
6740+ goto unlock;
67376741 prev_delta -= base_energy_pd;
67386742 best_delta = min(best_delta, prev_delta);
67396743 }
@@ -6741,6 +6745,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) · 1 unmodified line
67416745 /* Evaluate the energy impact of using max_spare_cap_cpu. */
67426746 if (max_spare_cap_cpu >= 0) {
67436747 cur_delta = compute_energy(p, max_spare_cap_cpu, pd);
6748+ if (cur_delta < base_energy_pd)
6749+ goto unlock;
67446750 cur_delta -= base_energy_pd;
67456751 if (cur_delta < best_delta) {
67466752 best_delta = cur_delta;
@@ -6748,25 +6754,22 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) · 1 unmodified line
67486754 }
67496755 }
67506756 }
6751−unlock:
67526757 rcu_read_unlock();
67536758
67546759 /*
67556760 * Pick the best CPU if prev_cpu cannot be used, or if it saves at
67566761 * least 6% of the energy used by prev_cpu.
67576762 */
6758− if (prev_delta == ULONG_MAX)
6759− return best_energy_cpu;
6763+ if ((prev_delta == ULONG_MAX) ||
6764+ (prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
6765+ target = best_energy_cpu;
67606766
6761− if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
6762− return best_energy_cpu;
6763−
6764− return prev_cpu;
6767+ return target;
67656768
6766−fail:
6769+unlock:
67676770 rcu_read_unlock();
67686771
6769− return -1;
6772+ return target;
67706773 }
67716774
67726775 /*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t