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
99259925 * from balancing the load across the system.
99269926 */
99279927 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,
99289938 /*
99299939 * The CPU is overloaded and can't provide expected CPU cycles to all
99309940 * tasks.
@@ -10828,6 +10838,7 @@ struct sg_lb_stats { · 897 unmodified lines
1082810838 enum group_type group_type;
1082910839 unsigned int group_asym_packing; /* Tasks should be moved to preferred CPU */
1083010840 unsigned int group_smt_balance; /* Task on busy SMT be moved */
10841+ unsigned int group_llc_balance; /* Tasks should be moved to preferred LLC */
1083110842 unsigned long group_misfit_task_load; /* A CPU has a task too big for its capacity */
1083210843 unsigned int group_overutilized; /* At least one CPU is overutilized in the group */
1083310844 #ifdef CONFIG_NUMA_BALANCING
@@ -11094,6 +11105,9 @@ group_type group_classify(unsigned int imbalance_pct, · 260 unmodified lines
1109411105 if (group_is_overloaded(imbalance_pct, sgs))
1109511106 return group_overloaded;
1109611107
11108+ if (sgs->group_llc_balance)
11109+ return group_llc_balance;
11110+
1109711111 if (sg_imbalanced(group))
1109811112 return group_imbalanced;
1109911113
@@ -11288,11 +11302,63 @@ static void record_sg_llc_stats(struct lb_env *env, · 188 unmodified lines
1128811302 if (unlikely(READ_ONCE(sd_share->capacity) != sgs->group_capacity))
1128911303 WRITE_ONCE(sd_share->capacity, sgs->group_capacity);
1129011304 }
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+ */
11310+static 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+
11335+static 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+}
1129111344 #else
1129211345 static inline void record_sg_llc_stats(struct lb_env *env, struct sg_lb_stats *sgs,
1129311346 struct sched_group *group)
1129411347 {
1129511348 }
11349+
11350+static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,
11351+ struct sched_group *group)
11352+{
11353+ return false;
11354+}
11355+
11356+static 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+}
1129611362 #endif
1129711363
1129811364 /**
@@ -11394,6 +11460,10 @@ static inline void update_sg_lb_stats(struct lb_env *env, · 95 unmodified lines
1139411460 /* Check for loaded SMT group to be balanced to dst CPU */
1139511461 if (smt_balance(env, sgs, group))
1139611462 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;
1139711467 }
1139811468
1139911469 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
1145711527 /* Select the overloaded group with highest avg_load. */
1145811528 return sgs->avg_load > busiest->avg_load;
1145911529
11530+ case group_llc_balance:
11531+ /* Select the group with most tasks preferring dst LLC */
11532+ return update_llc_busiest(env, busiest, sgs);
11533+
1146011534 case group_imbalanced:
1146111535 /*
1146211536 * 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
1171911793 return false;
1172011794 break;
1172111795
11796+ case group_llc_balance:
1172211797 case group_imbalanced:
1172311798 case group_asym_packing:
1172411799 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
1185111926 return NULL;
1185211927 break;
1185311928
11929+ case group_llc_balance:
1185411930 case group_imbalanced:
1185511931 case group_asym_packing:
1185611932 case group_smt_balance:
@@ -12349,7 +12425,8 @@ static struct sched_group *sched_balance_find_src_group(struct lb_env *env) · 492 unmodified lines
1234912425 * group's child domain.
1235012426 */
1235112427 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))
1235312430 goto force_balance;
1235412431
1235512432 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