java开发工程师,专注于内核源码,算法,数据结构。 qq:630501400
分类: C/C++
2013-03-13 23:35:15
CFS调度器选择vruntime最小的任务来进行调度,在更新vruntime的时候一个是要考虑当前时间和上次更新vruntime的时间差,二是要加权计算sched_entity的load。load的值依赖于当前sched_entity的nice值,在内核中这个nice和load的对应关系事先已经被计算好。
这些值的取值原因自己也没有搞清楚,看了注释大概明白。
大概的意思就是nice值的上升1级(越小执行优先级越高),也就意味着sched_entity的运行时间会减少。规定这个减少的幅度是10%,这个差距导致了两个sched_entityl的oad大概差了1.25倍,例子:两个sched_entity具有相同的nice,也就是各占50%的cpu时间,其中一个nice上升,导致了这个sched_entity cpu时间比之前少了10%,也就是一个sched_entity是55%,一个是45%,所以这个时候55和45大概差了1.25倍。
这样就有了 prio_to_weight数组。
还有数组,每个元素的值是1>>32/prio_to_weight每个元素的值。
这个数组的存在的意义很大,因为在更新vruntime的时候,时间差需要加权load,当nice=0表示不需要加权load计算。如果nice!=0那么需要按照当前的load和nice=0的load(nice=0的load=1024)的比例进行等比例缩减或者增加vruntime。
公式如下:
这里delta vruntime是vruntime的差值。deltaTime就是当前时间和上次计算的load的时间差,load就是当前sched_entity的load值,通过上面的公式可以看出,如果load越大,vruntime越小,cfs会通过红黑树选择出最需要调度的sched_entity,也就是vruntime最小的。
但是内核中会频繁统计这个delta vruntime,我们知道运算中,除法的运行周期十分长,这样就导致了计算delta vruntime会很慢。那么这个除法可以用乘法和位移运算来代替。
可以看出公式中,利用到了inv_load数组,这个数组事先缓存好了的值,然后最后结果在右移32位就是结果。
代码中,我想了很久才明白的一行代码:
注释的意思是,x右移y位,相当于然后结果,四舍五入。
可以知道1UL<<(y-1)相当于1<
SRR (10,2) 也就是10/4, 1010+0010=1100 >>2=0011=3
SRR (9,2) 就是9/4,1001+0010=1010>>2=0010=2
看了上面的例子也就清楚了,1UL<<(y-1)作用于y-1位(右边第一位是0位),如果为y-1位为1,就是产生了5入的情况,需要1UL<<(y-1)来帮助它进位,不被位移操作抵销掉。如果y-1位为0,那么也就是产生了4舍的情况,1UL<<(y-1)对它来说都是没有任何作用的,因为不会产生进位操作。
所以这个(1UL << ((y) – 1))是SRR操作能四舍五入的根本原因。
看下代码:
不明白的问题:在sched_entity更新weight的时候(update_load_add,update_load_sub)会把inv_weight置为0,导致在计算delta_vruntime的时候重新计算inv_weight,公式中的
lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2)/ (lw->weight+1) 是我不理解的,尤其是那个 lw->weight/2,有什么特殊的用意。希望看懂这行代码的同学能指点我一下。
djjsindy2013-04-23 14:01:23
nobodythere:1 + (WMULT_CONST-lw->weight/2)/ (lw->weight+1)
这个公式中,(lw->weight+1)如果是lw->weight的话,就好理解了,也是为了四舍五入。WMULT_CONST减去lw->weight的一半,如果原来除以lw->weight需要五入,那么除法的结果不变,除法结果再加1正好等于五入后的结果,如果需要四舍,结果必然比原结果小一,则正好加1进行补偿。
不过不知道(lw->weight+1)加1是为什么
确实,有道理那个四舍五入,,那个lw->weight+1,我觉得是因为在update_load_set和update_load_sub的时候,如果更新完weight为0了,那么到了这个地方的除法,肯定是出错的,发现在函数init_tg_cfs_entry函数中有这么一行代码:update_load_set(&se->load, 0);具体这个函数的作用我还不了解,还没看到,可以看到的是这个地方把se的load更新成了0,那么在计算新的load和invload 的时候就需要在你说的那个地方加1了,不加1除法出错。多亏了你的提醒,原来那段代码是四舍五入的意思。以后多多交流。
回复 | 举报nobodythere2013-04-22 21:18:46
1 + (WMULT_CONST-lw->weight/2)/ (lw->weight+1)
这个公式中,(lw->weight+1)如果是lw->weight的话,就好理解了,也是为了四舍五入。WMULT_CONST减去lw->weight的一半,如果原来除以lw->weight需要五入,那么除法的结果不变,除法结果再加1正好等于五入后的结果,如果需要四舍,结果必然比原结果小一,则正好加1进行补偿。
不过不知道(lw->weight+1)加1是为什么