調度子係統8_負載均衡(五)
// 計算group在給定domain中的imbalance // 調用路徑:find_busiest_group->calculate_imbalance // 函數參數: // sds:sched domain的統計信息 // this_cpu:當前正在運行load balance的cpu // imbalance:保存imbalance值 // 函數任務: // 1.計算最忙group內進程的平均負載 // 1.1 公式:最忙group當前的負載量/最忙group當前運行的進程數 // 2.如果最忙group失衡 // 2.1 最忙group內進程的平均負載 = min(最忙group的當前負載,sched doman的平均負載) // 3.如果最忙group的負載小於domain平均負載,則說明已經平衡,返回 // 4.如果最忙group沒有失衡 // 4.1 計算最忙group超過group容量的進程個數 // 5.計算load balance進行pull的load // 5.1 pull的load量為 min(最忙group超過domain平均負載的量,最忙group的超過容量的負載量) // 6.計算this_cpu所在group與最忙cpu所在group之間的imbalance量 // 6.1 imbalance量為 min(load balance進行pull的load,當前cpu所在group超過domain平均負載的量) // 7.如果imbalance不足最忙group中進程的平均負載 // 7.1 進行微調整 static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu, unsigned long *imbalance) { unsigned long max_pull, load_above_capacity = ~0UL; //計算最忙group內進程當前的平均負載 sds->busiest_load_per_task /= sds->busiest_nr_running; //如果最忙group失衡 if (sds->group_imb) { //則最忙group內進程的平均負載取 min(當前負載、曆史負載) sds->busiest_load_per_task = min(sds->busiest_load_per_task, sds->avg_load); } //如果最忙group的負載小於平均負載,則說明已平衡 if (sds->max_load < sds->avg_load) { //imbalance=0 *imbalance = 0; return fix_small_imbalance(sds, this_cpu, imbalance); } //沒有group失衡 if (!sds->group_imb) { //最忙group超過容量的進程數 load_above_capacity = (sds->busiest_nr_running - sds->busiest_group_capacity); load_above_capacity *= (SCHED_LOAD_SCALE * SCHED_LOAD_SCALE); load_above_capacity /= sds->busiest->cpu_power; } //計算load balance進行pull的load max_pull = min(sds->max_load - sds->avg_load, load_above_capacity); //計算imbalance *imbalance = min(max_pull * sds->busiest->cpu_power, (sds->avg_load - sds->this_load) * sds->this->cpu_power) / SCHED_LOAD_SCALE; //imbalance不足最忙group中進程的平均負載 if (*imbalance < sds->busiest_load_per_task) return fix_small_imbalance(sds, this_cpu, imbalance); } // 查找sched group中最忙的group // 函數任務: // 1.遍曆group內所有在線的cpu // 1.1 獲取cpu對應的rq的當前負載rq->load.weight // 1.2 如果rq當前隻有一個進程,並且負載大於imbalance,繼續1.1 // 1.3 通過cpu power計算cpu的負載 // 1.3.1 為方便在不同cpu見進行比較 // 1.4 記錄負載最大的cpu // 2.返回最忙的cpu // 調用路徑:load_balance->find_busiest_queue 2.1 static struct rq *find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle, unsigned long imbalance, const struct cpumask *cpus) { struct rq *busiest = NULL, *rq; unsigned long max_load = 0; int i; //遍曆group內的cpu for_each_cpu(i, sched_group_cpus(group)) { unsigned long power = power_of(i); unsigned long capacity = DIV_ROUND_CLOSEST(power, SCHED_LOAD_SCALE); unsigned long wl; //cpu在線 if (!cpumask_test_cpu(i, cpus)) continue; //cpu的rq rq = cpu_rq(i); //rq當前的負載 wl = weighted_cpuload(i); //rq當前隻有一個進程,則返回 if (capacity && rq->nr_running == 1 && wl > imbalance) continue; //通過cpu power計算cpu的負載 wl = (wl * SCHED_LOAD_SCALE) / power; //記錄最大負載的cpu if (wl > max_load) { max_load = wl; busiest = rq; } } //返回最忙的cpu return busiest; } // 獲取cpu power // 函數任務: // 1.如果cpu沒有對應的group,返回SCHED_LOAD_SCALE // 2.否則返回對應group的power 2.2 static unsigned long power_of(int cpu) { //獲取cpu對應的group struct sched_group *group = group_of(cpu); //沒有對應的group,返回SCHED_LOAD_SCALE if (!group) return SCHED_LOAD_SCALE; //否則返回group的power return group->cpu_power; }
最後更新:2017-04-03 12:53:54