cpu capacity、task_util、cpu_util是如何計算的?


在進程調度中使用到了一些比較關鍵的參數,用來作為調度、cpu調頻、EAS等關鍵功能的前提。

並且在相關模塊中經常交替出現,比較容易混淆,這里單獨將這些參數拎出來,做個記錄。

cpu_capacity

cpu_capacity是作為cpu算力的量化體現,代表着cpu性能的大小。數字越大,性能越高。

cpu的性能和cpu的運行頻率是正相關的,頻率越高,性能也越好。所以,在大cluster內cpu的max_capacity比小cluster內的cpu max_capacity更大。

計算公式有2個,一個是cpu最大的capacity:cpu_max_capacity;另一個是當前freq下的cpu capacity。

如下:

 

 獲取cpu capacity的代碼:

static inline unsigned long capacity_of(int cpu)    //cpu_capacity_orig基礎上去掉rt、dl以及irq util后的capacity
{                                //計算:(capacity_orig - rt_util - dl_util)*(capacity_orig - irq_util) / capacity_orig
    return cpu_rq(cpu)->cpu_capacity;
}

static inline unsigned long capacity_orig_of(int cpu)  //獲取當前policy_max_freq下的capacity(可能被thermal影響而縮小) { return cpu_rq(cpu)->cpu_capacity_orig; }

 

Task util 

task util是用來表示一個task大小,它會占用cpu多少算力,或者說是給cpu造成多少負載的體現。task util的監控是通過WALT得到,所以公式中一些參數也與WALT的配置有關。

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

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

 

特別地,打開了schedtune的boost之后,task util也會進行變化。公式如下:

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

獲取task util代碼:

static inline unsigned long task_util(struct task_struct *p)
{
#ifdef CONFIG_SCHED_WALT
    return p->ravg.demand_scaled;
#endif
    return READ_ONCE(p->se.avg.util_avg);
}

 

CPU util

cpu util則表示當前有多少工作量在該cpu上,是cpu負載的體現。也是通過WALT機制監控得到:cumulative_runnable_avg_scaled

它是統計了當前一個WALT window中on_rq ==1的所有task util的總和

cpu util = ∑ task_util(x) ---表示所有on_rq的task util總和

    ∑demand(x) * 1024 / window_size ---∑demand(x) 表示cpu rq中所有runnable的task demand

 

獲取cpu_util的代碼:

static inline unsigned long cpu_util(int cpu)
{
    struct cfs_rq *cfs_rq;
    unsigned int util;

#ifdef CONFIG_SCHED_WALT
    u64 walt_cpu_util =
        cpu_rq(cpu)->walt_stats.cumulative_runnable_avg_scaled;  //cpu負載

    return min_t(unsigned long, walt_cpu_util, capacity_orig_of(cpu));
#endif

    cfs_rq = &cpu_rq(cpu)->cfs;
    util = READ_ONCE(cfs_rq->avg.util_avg);

    if (sched_feat(UTIL_EST))
        util = max(util, READ_ONCE(cfs_rq->avg.util_est.enqueued));

    return min_t(unsigned long, util, capacity_orig_of(cpu));
}

 

最后提一下schedutil的調頻怎么計算的:

         1.25 * cpuinfo.max_freq
f = ———————————————————————————————— * boosted_util
            cpu_max_capacity

         1.25 * cpuinfo.max_freq
  = ———————————————————————————————— * [util + (1024 - util) * boost_percent],(boost_percent是schedtune配置的boost值)
            cpu_max_capacity


其中util計算公式如下:
prev_runnable_sum
* (100 + sched_load_boost) util = ———————————————————————————————————————————————————————, (prev_runnable_sum是WALT統計的值,window_size默認20ms) window_size >> 10 * 100

cpuinfo.max_freq現在還有點混淆,之后有空再check清楚到底是不是cpu最大freq?

prev_runnable_sum實際在代碼中還會加上一個grp的load。這塊屬於walt,后續學習schedutil,需要仔細搞清楚。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM