內核調度【七】【boosted_task_util】

boosted_task_util實際上包含兩個部分,當前task的util加上margin值,margin就是將util的值給他擴大或者縮小一定的倍數

boosted_task_util

static inline unsigned long
boosted_task_util(struct task_struct *task)
{
	unsigned long util = task_util_est(task);//這裏我們假設walt機制是open的
	long margin = schedtune_task_margin(task);//margin就是sign除以100

	trace_sched_boost_task(task, util, margin);//添加到內核trace log裏面

	return util + margin;
}

task_util & task_util_est

task util = demand *1024 / window_size  ---其中demand爲WALT機制中sum_history數組得到的max(latest值,平均值),window_size則是WALT機制中window的大小(默認爲20ms

 

未開啓boost    = (delta / window_size) * (cur_freq / max_freq) * cpu_max_capacity ---delta是task在一個window中運行的真實時間;cur_freq爲cpu當前頻率;max_freq爲cpu最大頻率;

 

開啓boost  task util也會進行變化。公式如下:

boosted task util = task_util +(1024 - task_util)* boost_percent ---boost_percent是schedtune中配置的boost百分比

static inline unsigned long task_util(struct task_struct *p)
{
#ifdef CONFIG_SCHED_WALT
	if (likely(!walt_disabled && sysctl_sched_use_walt_task_util))
		return (p->ravg.demand /
			(walt_ravg_window >> SCHED_CAPACITY_SHIFT));
#endif
	return READ_ONCE(p->se.avg.util_avg);
}

Task­­ utilization 的估算也是依賴walt進行窗口的統計

static inline unsigned long task_util_est(struct task_struct *p)
{
#ifdef CONFIG_SCHED_WALT
	if (likely(!walt_disabled && sysctl_sched_use_walt_task_util))
		return (p->ravg.demand /
			(walt_ravg_window >> SCHED_CAPACITY_SHIFT));
#endif
	return max(task_util(p), _task_util_est(p));
}

_task_util_est

task util是用來表示一個task大小,它會佔用cpu多少算力,或者說是給cpu造成多少負載的體現

static inline unsigned long _task_util_est(struct task_struct *p)
{
	struct util_est ue = READ_ONCE(p->se.avg.util_est);//這裏應該是讀取一次一個數據結構的宏

	return max(ue.ewma, ue.enqueued);
}

關於struct util_est,可以看https://blog.csdn.net/feifei_csdn/article/details/107106149

struct util_est {

    unsigned int            enqueued;入隊列時估算的task的效力

unsigned int            ewma;指數加權動態的平均task的效力

schedtune_task_margin

static inline long
schedtune_task_margin(struct task_struct *task)
{
	int boost = schedtune_task_boost(task);//返回的應該是我們設置的值-100到100
	unsigned long util;
	long margin;

	if (boost == 0)
		return 0;

	util = task_util_est(task);
	margin = schedtune_margin(util, boost);//對util進行一定的縮放

	return margin;
}

schedtune_margin

對uti進行成比例的縮放

unsigned int spc_threshold = 100;
struct reciprocal_value schedtune_spc_rdiv;
static long
schedtune_margin(unsigned long signal, long boost)
{
	long long margin = 0;

	/*
	 * Signal proportional(成比例的) compensation(補償)(SPC)
	 *
	 * The Boost (B) value is used to compute a Margin (M) which is
	 * proportional to the complement of the original Signal (S):
	 *   M = B * (SCHED_CAPACITY_SCALE - S)
	 * The obtained M could be used by the caller to "boost" S.
	 */
	if (boost >= 0) {
		if (signal < spc_threshold)
			margin = signal * boost;
		else {
			margin  = SCHED_CAPACITY_SCALE - signal;
			margin *= boost;
		}
	} else
		margin = -signal * boost;

	margin  = reciprocal_divide(margin, schedtune_spc_rdiv);

// reciprocal_divide是計算A/B的優化函數

	if (boost < 0)
		margin *= -1;
	return margin;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章