aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Rasmussen <morten.rasmussen@arm.com>2018-07-04 06:17:42 -0400
committerIngo Molnar <mingo@kernel.org>2018-09-10 05:05:50 -0400
commitcad68e552e7774b68ae6a2c5fedb792936098b72 (patch)
tree9b669325762b3d94fff89a5e3f27c32d48366273
parente3d6d0cb66f2351cbfd09fbae04eb9804afe9577 (diff)
sched/fair: Consider misfit tasks when load-balancing
On asymmetric CPU capacity systems load intensive tasks can end up on CPUs that don't suit their compute demand. In this scenarios 'misfit' tasks should be migrated to CPUs with higher compute capacity to ensure better throughput. group_misfit_task indicates this scenario, but tweaks to the load-balance code are needed to make the migrations happen. Misfit balancing only makes sense between a source group of lower per-CPU capacity and destination group of higher compute capacity. Otherwise, misfit balancing is ignored. group_misfit_task has lowest priority so any imbalance due to overload is dealt with first. The modifications are: 1. Only pick a group containing misfit tasks as the busiest group if the destination group has higher capacity and has spare capacity. 2. When the busiest group is a 'misfit' group, skip the usual average load and group capacity checks. 3. Set the imbalance for 'misfit' balancing sufficiently high for a task to be pulled ignoring average load. 4. Pick the CPU with the highest misfit load as the source CPU. 5. If the misfit task is alone on the source CPU, go for active balancing. Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: dietmar.eggemann@arm.com Cc: gaku.inami.xh@renesas.com Cc: valentin.schneider@arm.com Cc: vincent.guittot@linaro.org Link: http://lkml.kernel.org/r/1530699470-29808-5-git-send-email-morten.rasmussen@arm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/sched/fair.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index fe04315d57b3..24fe39e57bc3 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6890,6 +6890,7 @@ struct lb_env {
6890 unsigned int loop_max; 6890 unsigned int loop_max;
6891 6891
6892 enum fbq_type fbq_type; 6892 enum fbq_type fbq_type;
6893 enum group_type src_grp_type;
6893 struct list_head tasks; 6894 struct list_head tasks;
6894}; 6895};
6895 6896
@@ -7873,6 +7874,17 @@ static bool update_sd_pick_busiest(struct lb_env *env,
7873{ 7874{
7874 struct sg_lb_stats *busiest = &sds->busiest_stat; 7875 struct sg_lb_stats *busiest = &sds->busiest_stat;
7875 7876
7877 /*
7878 * Don't try to pull misfit tasks we can't help.
7879 * We can use max_capacity here as reduction in capacity on some
7880 * CPUs in the group should either be possible to resolve
7881 * internally or be covered by avg_load imbalance (eventually).
7882 */
7883 if (sgs->group_type == group_misfit_task &&
7884 (!group_smaller_max_cpu_capacity(sg, sds->local) ||
7885 !group_has_capacity(env, &sds->local_stat)))
7886 return false;
7887
7876 if (sgs->group_type > busiest->group_type) 7888 if (sgs->group_type > busiest->group_type)
7877 return true; 7889 return true;
7878 7890
@@ -7895,6 +7907,13 @@ static bool update_sd_pick_busiest(struct lb_env *env,
7895 group_smaller_min_cpu_capacity(sds->local, sg)) 7907 group_smaller_min_cpu_capacity(sds->local, sg))
7896 return false; 7908 return false;
7897 7909
7910 /*
7911 * If we have more than one misfit sg go with the biggest misfit.
7912 */
7913 if (sgs->group_type == group_misfit_task &&
7914 sgs->group_misfit_task_load < busiest->group_misfit_task_load)
7915 return false;
7916
7898asym_packing: 7917asym_packing:
7899 /* This is the busiest node in its class. */ 7918 /* This is the busiest node in its class. */
7900 if (!(env->sd->flags & SD_ASYM_PACKING)) 7919 if (!(env->sd->flags & SD_ASYM_PACKING))
@@ -8192,8 +8211,9 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
8192 * factors in sg capacity and sgs with smaller group_type are 8211 * factors in sg capacity and sgs with smaller group_type are
8193 * skipped when updating the busiest sg: 8212 * skipped when updating the busiest sg:
8194 */ 8213 */
8195 if (busiest->avg_load <= sds->avg_load || 8214 if (busiest->group_type != group_misfit_task &&
8196 local->avg_load >= sds->avg_load) { 8215 (busiest->avg_load <= sds->avg_load ||
8216 local->avg_load >= sds->avg_load)) {
8197 env->imbalance = 0; 8217 env->imbalance = 0;
8198 return fix_small_imbalance(env, sds); 8218 return fix_small_imbalance(env, sds);
8199 } 8219 }
@@ -8227,6 +8247,12 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
8227 (sds->avg_load - local->avg_load) * local->group_capacity 8247 (sds->avg_load - local->avg_load) * local->group_capacity
8228 ) / SCHED_CAPACITY_SCALE; 8248 ) / SCHED_CAPACITY_SCALE;
8229 8249
8250 /* Boost imbalance to allow misfit task to be balanced. */
8251 if (busiest->group_type == group_misfit_task) {
8252 env->imbalance = max_t(long, env->imbalance,
8253 busiest->group_misfit_task_load);
8254 }
8255
8230 /* 8256 /*
8231 * if *imbalance is less than the average load per runnable task 8257 * if *imbalance is less than the average load per runnable task
8232 * there is no guarantee that any tasks will be moved so we'll have 8258 * there is no guarantee that any tasks will be moved so we'll have
@@ -8293,6 +8319,10 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
8293 busiest->group_no_capacity) 8319 busiest->group_no_capacity)
8294 goto force_balance; 8320 goto force_balance;
8295 8321
8322 /* Misfit tasks should be dealt with regardless of the avg load */
8323 if (busiest->group_type == group_misfit_task)
8324 goto force_balance;
8325
8296 /* 8326 /*
8297 * If the local group is busier than the selected busiest group 8327 * If the local group is busier than the selected busiest group
8298 * don't try and pull any tasks. 8328 * don't try and pull any tasks.
@@ -8330,6 +8360,7 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
8330 8360
8331force_balance: 8361force_balance:
8332 /* Looks like there is an imbalance. Compute it */ 8362 /* Looks like there is an imbalance. Compute it */
8363 env->src_grp_type = busiest->group_type;
8333 calculate_imbalance(env, &sds); 8364 calculate_imbalance(env, &sds);
8334 return env->imbalance ? sds.busiest : NULL; 8365 return env->imbalance ? sds.busiest : NULL;
8335 8366
@@ -8377,6 +8408,19 @@ static struct rq *find_busiest_queue(struct lb_env *env,
8377 if (rt > env->fbq_type) 8408 if (rt > env->fbq_type)
8378 continue; 8409 continue;
8379 8410
8411 /*
8412 * For ASYM_CPUCAPACITY domains with misfit tasks we simply
8413 * seek the "biggest" misfit task.
8414 */
8415 if (env->src_grp_type == group_misfit_task) {
8416 if (rq->misfit_task_load > busiest_load) {
8417 busiest_load = rq->misfit_task_load;
8418 busiest = rq;
8419 }
8420
8421 continue;
8422 }
8423
8380 capacity = capacity_of(i); 8424 capacity = capacity_of(i);
8381 8425
8382 wl = weighted_cpuload(rq); 8426 wl = weighted_cpuload(rq);
@@ -8446,6 +8490,9 @@ static int need_active_balance(struct lb_env *env)
8446 return 1; 8490 return 1;
8447 } 8491 }
8448 8492
8493 if (env->src_grp_type == group_misfit_task)
8494 return 1;
8495
8449 return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2); 8496 return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
8450} 8497}
8451 8498