【问题标题】:Explanation of the calc_delta_mine functioncalc_delta_mine 函数说明
【发布时间】:2013-07-21 20:11:52
【问题描述】:

我目前正在阅读 Robert Love 的“Linux Kernel Development”,我收到了一些关于 CFS 的问题。 我的问题是 calc_delta_mine 如何计算:

delta_exec_weighted= (delta_exec * weight)/lw->weight

我猜它是通过两个步骤完成的:

  1. 计算 (delta_exec * 1024) :

     if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
     tmp = (u64)delta_exec * scale_load_down(weight);
       else
     tmp = (u64)delta_exec;
    
  2. 计算 /lw->weight(或 * lw->inv_weight ):

      if (!lw->inv_weight) {
      unsigned long w = scale_load_down(lw->weight);
      if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
                lw->inv_weight = 1;
        else if (unlikely(!w))
                lw->inv_weight = WMULT_CONST;
        else
                lw->inv_weight = WMULT_CONST / w;
     }
    
     /*
      * Check whether we'd overflow the 64-bit multiplication:
      */
     if (unlikely(tmp > WMULT_CONST))
             tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
                     WMULT_SHIFT/2);
     else
             tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
    
     return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
    

SRR(右移和舍入)宏通过以下方式定义:

    #define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))

其他宏定义:

    #if BITS_PER_LONG == 32
    # define WMULT_CONST    (~0UL)
    #else
    # define WMULT_CONST    (1UL << 32)
    #endif
    #define WMULT_SHIFT     32

谁能解释一下 SRR 的工作原理以及它如何检查 64 位乘法溢出? 请解释一下这个函数中宏的定义((~0UL) ,(1UL

【问题讨论】:

    标签: linux-kernel scheduling


    【解决方案1】:

    您发布的代码基本上是使用 32.32 定点算术进行计算,其中单个 64 位数量在高 32 位中保存数字的整数部分,在低 32 位中保存数字的小数部分(例如,在这个系统中,1.5 是 0x0000000180000000)。因此,WMULT_CONST 是 1.0 的近似值(出于平台效率的考虑,使用一个可以放入 long 的值),因此将WMULT_CONST 除以w 计算出1/w 为32.32 值。

    请注意,将两个 32.32 值作为整数相乘会产生大于 232 倍的结果;因此,WMULT_SHIFT (=32) 是将两个 32.32 值相乘的结果归一化回到 32.32 所需的右移值。

    sched/sched.h 中的评论解释了将这种改进的精度用于调度目的的必要性:

    /*
     * Increase resolution of nice-level calculations for 64-bit architectures.
     * The extra resolution improves shares distribution and load balancing of
     * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
     * hierarchies, especially on larger systems. This is not a user-visible change
     * and does not change the user-interface for setting shares/weights.
     *
     * We increase resolution only if we have enough bits to allow this increased
     * resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution
     * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the
     * increased costs.
     */
    

    对于SRR,从数学上讲,它计算了x / 2<sup>y</sup>四舍五入结果。

    要对除法x/q 的结果进行四舍五入,您可以计算x + q/2 floor-divided by q;这就是 SRR 通过计算 x + 2<sup>y-1</sup> 地板除以 2<sup>y</sup> 所做的。

    【讨论】:

    • 谢谢。所以如果我再看一下 SRR 宏,我就会明白 (1UL &lt;&lt; ((y) - 1))2^(y-1) ,而 ((x) + (1UL &lt;&lt; ((y) - 1))) x + 2^(y-1)。所以最后一部分是获取结果并将其转移到&gt;&gt; (y) 以将其从 32.32 恢复为原始表示?
    • &gt;&gt; (y)地板除以 2^ySRR 只适用于整数;它不关心结果是否为 32.32。 calc_delta_mine 用它来计算 32.32 个数字。
    • 似乎 tmp 是整数形式:tmp = (u64)delta_exec * scale_load_down(weight); lw-&gt;inv_weight = WMULT_CONST / w 是 32.32 形式。我认为通过将乘法转移到&gt;&gt;32 我再次将其转换为整数形式,这种更有意义,因为 vruntime 是一个整数,不应该表示为 32.32。
    猜你喜欢
    • 2013-12-23
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    相关资源
    最近更新 更多