History

sched/cache: Prioritize tasks preferring destination LLC during balancing

During LLC load balancing, first check for tasks that prefer the destination LLC and balance them to it before others. Mark source sched groups containing tasks preferring non local LLCs with the group_llc_balance flag. This ensures the load balancer later pulls or pushes these tasks toward their preferred LLCs. The priority of group_llc_balance is lower than that of group_overloaded and higher than that of all other group types. This is because group_llc_balance may exacerbate load imbalance, and if the LLC balancing attempt fails, the nr_balance_failed mechanism will trigger other group types to rebalance the load. The load balancer selects the busiest sched_group and migrates tasks to less busy groups to distribute load across CPUs. With cache-aware scheduling enabled, the busiest sched_group is the one with most tasks preferring the destination LLC. If the group has the llc_balance flag set, cache aware load balancing is triggered. Introduce the helper function update_llc_busiest() to identify the sched_group with the most tasks preferring the destination LLC.

Tim Chen committed 7 months ago

Commit f38cc2f1 parent 9a5e22f1 file · +78 −1Browse files

Unified · Split

kernel/sched/fair.c+78−1
@@ -9925,6 +9925,16 @@ enum group_type { · 9924 unmodified lines
9925 * from balancing the load across the system.9925 * from balancing the load across the system.
9926 */9926 */
9927 group_imbalanced,9927 group_imbalanced,
9928 /*
9929 * There are tasks running on non-preferred LLC, possible to move
9930 * them to their preferred LLC without creating too much imbalance.
9931 * The priority of group_llc_balance is lower than that of
9932 * group_overloaded and higher than that of all other group types.
9933 * This is because group_llc_balance may exacerbate load imbalance.
9934 * If the LLC balancing attempt fails, the nr_balance_failed
9935 * mechanism will trigger other group types to rebalance the load.
9936 */
9937 group_llc_balance,
9928 /*9938 /*
9929 * The CPU is overloaded and can't provide expected CPU cycles to all9939 * The CPU is overloaded and can't provide expected CPU cycles to all
9930 * tasks.9940 * tasks.
@@ -10828,6 +10838,7 @@ struct sg_lb_stats { · 897 unmodified lines
10828 enum group_type group_type;10838 enum group_type group_type;
10829 unsigned int group_asym_packing; /* Tasks should be moved to preferred CPU */10839 unsigned int group_asym_packing; /* Tasks should be moved to preferred CPU */
10830 unsigned int group_smt_balance; /* Task on busy SMT be moved */10840 unsigned int group_smt_balance; /* Task on busy SMT be moved */
10841 unsigned int group_llc_balance; /* Tasks should be moved to preferred LLC */
10831 unsigned long group_misfit_task_load; /* A CPU has a task too big for its capacity */10842 unsigned long group_misfit_task_load; /* A CPU has a task too big for its capacity */
10832 unsigned int group_overutilized; /* At least one CPU is overutilized in the group */10843 unsigned int group_overutilized; /* At least one CPU is overutilized in the group */
10833#ifdef CONFIG_NUMA_BALANCING10844#ifdef CONFIG_NUMA_BALANCING
@@ -11094,6 +11105,9 @@ group_type group_classify(unsigned int imbalance_pct, · 260 unmodified lines
11094 if (group_is_overloaded(imbalance_pct, sgs))11105 if (group_is_overloaded(imbalance_pct, sgs))
11095 return group_overloaded;11106 return group_overloaded;
11096 11107
11108 if (sgs->group_llc_balance)
11109 return group_llc_balance;
11110
11097 if (sg_imbalanced(group))11111 if (sg_imbalanced(group))
11098 return group_imbalanced;11112 return group_imbalanced;
11099 11113
@@ -11288,11 +11302,63 @@ static void record_sg_llc_stats(struct lb_env *env, · 188 unmodified lines
11288 if (unlikely(READ_ONCE(sd_share->capacity) != sgs->group_capacity))11302 if (unlikely(READ_ONCE(sd_share->capacity) != sgs->group_capacity))
11289 WRITE_ONCE(sd_share->capacity, sgs->group_capacity);11303 WRITE_ONCE(sd_share->capacity, sgs->group_capacity);
11290}11304}
11305
11306/*
11307 * Do LLC balance on sched group that contains LLC, and have tasks preferring
11308 * to run on LLC in idle dst_cpu.
11309 */
11310static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,
11311 struct sched_group *group)
11312{
11313 if (!sched_cache_enabled())
11314 return false;
11315
11316 if (env->sd->flags & SD_SHARE_LLC)
11317 return false;
11318
11319 /*
11320 * Skip cache aware tagging if nr_balanced_failed is sufficiently high.
11321 * Threshold of cache_nice_tries is set to 1 higher than nr_balance_failed
11322 * to avoid excessive task migration at the same time.
11323 */
11324 if (env->sd->nr_balance_failed >= env->sd->cache_nice_tries + 1)
11325 return false;
11326
11327 if (sgs->nr_pref_dst_llc &&
11328 can_migrate_llc(cpumask_first(sched_group_span(group)),
11329 env->dst_cpu, 0, true) == mig_llc)
11330 return true;
11331
11332 return false;
11333}
11334
11335static bool update_llc_busiest(struct lb_env *env,
11336 struct sg_lb_stats *busiest,
11337 struct sg_lb_stats *sgs)
11338{
11339 /*
11340 * There are more tasks that want to run on dst_cpu's LLC.
11341 */
11342 return sgs->nr_pref_dst_llc > busiest->nr_pref_dst_llc;
11343}
11291#else11344#else
11292static inline void record_sg_llc_stats(struct lb_env *env, struct sg_lb_stats *sgs,11345static inline void record_sg_llc_stats(struct lb_env *env, struct sg_lb_stats *sgs,
11293 struct sched_group *group)11346 struct sched_group *group)
11294{11347{
11295}11348}
11349
11350static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,
11351 struct sched_group *group)
11352{
11353 return false;
11354}
11355
11356static bool update_llc_busiest(struct lb_env *env,
11357 struct sg_lb_stats *busiest,
11358 struct sg_lb_stats *sgs)
11359{
11360 return false;
11361}
11296#endif11362#endif
11297 11363
11298/**11364/**
@@ -11394,6 +11460,10 @@ static inline void update_sg_lb_stats(struct lb_env *env, · 95 unmodified lines
11394 /* Check for loaded SMT group to be balanced to dst CPU */11460 /* Check for loaded SMT group to be balanced to dst CPU */
11395 if (smt_balance(env, sgs, group))11461 if (smt_balance(env, sgs, group))
11396 sgs->group_smt_balance = 1;11462 sgs->group_smt_balance = 1;
11463
11464 /* Check for tasks in this group can be moved to their preferred LLC */
11465 if (llc_balance(env, sgs, group))
11466 sgs->group_llc_balance = 1;
11397 }11467 }
11398 11468
11399 sgs->group_type = group_classify(env->sd->imbalance_pct, group, sgs);11469 sgs->group_type = group_classify(env->sd->imbalance_pct, group, sgs);
@@ -11457,6 +11527,10 @@ static bool update_sd_pick_busiest(struct lb_env *env, · 57 unmodified lines
11457 /* Select the overloaded group with highest avg_load. */11527 /* Select the overloaded group with highest avg_load. */
11458 return sgs->avg_load > busiest->avg_load;11528 return sgs->avg_load > busiest->avg_load;
11459 11529
11530 case group_llc_balance:
11531 /* Select the group with most tasks preferring dst LLC */
11532 return update_llc_busiest(env, busiest, sgs);
11533
11460 case group_imbalanced:11534 case group_imbalanced:
11461 /*11535 /*
11462 * Select the 1st imbalanced group as we don't have any way to11536 * Select the 1st imbalanced group as we don't have any way to
@@ -11719,6 +11793,7 @@ static bool update_pick_idlest(struct sched_group *idlest, · 256 unmodified lines
11719 return false;11793 return false;
11720 break;11794 break;
11721 11795
11796 case group_llc_balance:
11722 case group_imbalanced:11797 case group_imbalanced:
11723 case group_asym_packing:11798 case group_asym_packing:
11724 case group_smt_balance:11799 case group_smt_balance:
@@ -11851,6 +11926,7 @@ sched_balance_find_dst_group(struct sched_domain *sd, struct task_struct *p, int · 126 unmodified lines
11851 return NULL;11926 return NULL;
11852 break;11927 break;
11853 11928
11929 case group_llc_balance:
11854 case group_imbalanced:11930 case group_imbalanced:
11855 case group_asym_packing:11931 case group_asym_packing:
11856 case group_smt_balance:11932 case group_smt_balance:
@@ -12349,7 +12425,8 @@ static struct sched_group *sched_balance_find_src_group(struct lb_env *env) · 492 unmodified lines
12349 * group's child domain.12425 * group's child domain.
12350 */12426 */
12351 if (sds.prefer_sibling && local->group_type == group_has_spare &&12427 if (sds.prefer_sibling && local->group_type == group_has_spare &&
12352 sibling_imbalance(env, &sds, busiest, local) > 1)12428 (busiest->group_type == group_llc_balance ||
12429 sibling_imbalance(env, &sds, busiest, local) > 1))
12353 goto force_balance;12430 goto force_balance;
12354 12431
12355 if (busiest->group_type != group_overloaded) {12432 if (busiest->group_type != group_overloaded) {

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