sched/numa: Stop an exhastive search if a reasonable swap candidate or idle CPU is...
authorMel Gorman <mgorman@techsingularity.net>
Mon, 24 Feb 2020 09:52:23 +0000 (09:52 +0000)
committerIngo Molnar <mingo@kernel.org>
Mon, 24 Feb 2020 10:36:40 +0000 (11:36 +0100)
When domains are imbalanced or overloaded a search of all CPUs on the
target domain is searched and compared with task_numa_compare. In some
circumstances, a candidate is found that is an obvious win.

 o A task can move to an idle CPU and an idle CPU is found
 o A swap candidate is found that would move to its preferred domain

This patch terminates the search when either condition is met.

Signed-off-by: Mel Gorman <mgorman@techsingularity.net>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Valentin Schneider <valentin.schneider@arm.com>
Cc: Phil Auld <pauld@redhat.com>
Cc: Hillf Danton <hdanton@sina.com>
Link: https://lore.kernel.org/r/20200224095223.13361-14-mgorman@techsingularity.net
kernel/sched/fair.c

index 8c1ac01..fcc9686 100644 (file)
@@ -1707,7 +1707,7 @@ static bool load_too_imbalanced(long src_load, long dst_load,
  * into account that it might be best if task running on the dst_cpu should
  * be exchanged with the source task
  */
-static void task_numa_compare(struct task_numa_env *env,
+static bool task_numa_compare(struct task_numa_env *env,
                              long taskimp, long groupimp, bool maymove)
 {
        struct numa_group *cur_ng, *p_ng = deref_curr_numa_group(env->p);
@@ -1718,9 +1718,10 @@ static void task_numa_compare(struct task_numa_env *env,
        int dist = env->dist;
        long moveimp = imp;
        long load;
+       bool stopsearch = false;
 
        if (READ_ONCE(dst_rq->numa_migrate_on))
-               return;
+               return false;
 
        rcu_read_lock();
        cur = rcu_dereference(dst_rq->curr);
@@ -1731,8 +1732,10 @@ static void task_numa_compare(struct task_numa_env *env,
         * Because we have preemption enabled we can get migrated around and
         * end try selecting ourselves (current == env->p) as a swap candidate.
         */
-       if (cur == env->p)
+       if (cur == env->p) {
+               stopsearch = true;
                goto unlock;
+       }
 
        if (!cur) {
                if (maymove && moveimp >= env->best_imp)
@@ -1860,8 +1863,27 @@ assign:
        }
 
        task_numa_assign(env, cur, imp);
+
+       /*
+        * If a move to idle is allowed because there is capacity or load
+        * balance improves then stop the search. While a better swap
+        * candidate may exist, a search is not free.
+        */
+       if (maymove && !cur && env->best_cpu >= 0 && idle_cpu(env->best_cpu))
+               stopsearch = true;
+
+       /*
+        * If a swap candidate must be identified and the current best task
+        * moves its preferred node then stop the search.
+        */
+       if (!maymove && env->best_task &&
+           env->best_task->numa_preferred_nid == env->src_nid) {
+               stopsearch = true;
+       }
 unlock:
        rcu_read_unlock();
+
+       return stopsearch;
 }
 
 static void task_numa_find_cpu(struct task_numa_env *env,
@@ -1916,7 +1938,8 @@ static void task_numa_find_cpu(struct task_numa_env *env,
                        continue;
 
                env->dst_cpu = cpu;
-               task_numa_compare(env, taskimp, groupimp, maymove);
+               if (task_numa_compare(env, taskimp, groupimp, maymove))
+                       break;
        }
 }