2013-07-21 99 views
3

我正在閱讀Robert Love的「Linux Kernel Development」,並且我收到了一些關於CFS的問題。 我的問題是calc_delta_mine如何計算:calc_delta_mine函數的說明

delta_exec_weighted =(delta_exec *重)/ LW->重

我猜它是由兩個步驟完成:

  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->重量(或* 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位乘法溢出? 請解釋此函數中MACROS的定義((〜0UL),(1UL < < 32))?

回答

4

您發佈的代碼基本上是使用32.32定點算法進行計算,其中一個64位數量包含高32位數的整數部分,並且該數的小數部分位於低32位位(例如,在該系統中,1.5是0x0000000180000000)。因此,WMULT_CONST是近似值1.0(使用適合於平臺效率考慮因素的long的值),因此WMULT_CONST除以w計算1/w爲32.32值。

請注意,將兩個32.32值一起乘以整數會產生太大的結果;因此,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/2y結果。

要四捨五入x/q的結果,您可以計算x + q/2除以q;這是SRR通過計算x + 2y-1除以2y所做的。

+0

謝謝。所以如果我再看看SRR宏,我明白'(1UL <<((y)-1))是'2 ^(y-1)',並且'((x)+(1UL << (y)-1)))是'x + 2 ^(y-1)'。那麼最後一部分是取得結果並將其轉換成「>>(y)」以將其從32.32恢復爲原始表示? – arkadish

+0

'>>(y)'是2 * y *的* floor劃分。 'SRR'只對整數有效;它不關心結果是否爲32.32。'calc_delta_mine'使用它來計算32.32數字。 – nneonneo

+0

看起來tmp是整數形式:'tmp =(u64)delta_exec * scale_load_down(weight);'當'lw-> inv_weight = WMULT_CONST/w'爲32.32形式時。我認爲通過將乘以32 >>的乘法運算轉換爲整數形式,這種做法更有意義,因爲vruntime是一個整數,不應該表示爲32.32。 – arkadish