BogoMIPs function 解釋
在 /usr/src/linux/init/calibrate.c 有一個函式,是可以算出CPU一秒鐘可以跑幾條指令,今天在車上看這段碼想了半小時還是沒想通,回來拿個筆畫一下就通了~
所以下面紀錄一下,以免將來又忘記了~
1: #define LPS_PREC 8
2:
3: void __cpuinit calibrate_delay(void)
4: {
5: loops_per_jiffy = (1<<12);
6: while ((loops_per_jiffy <<= 1) != 0) {
7: /* wait for "start of" clock tick */
8: ticks = jiffies;
9: while (ticks == jiffies)
10: /* nothing */;
11: /* Go .. */
12: ticks = jiffies;
13: __delay(loops_per_jiffy);
14: ticks = jiffies - ticks;
15: if (ticks)
16: break;
17: }
18:
19: /*
20: * Do a binary approximation to get loops_per_jiffy set to
21: * equal one clock (up to lps_precision bits)
22: */
23: loops_per_jiffy >>= 1;
24: loopbit = loops_per_jiffy;
25: while (lps_precision-- && (loopbit >>= 1)) {
26: loops_per_jiffy |= loopbit;
27: ticks = jiffies;
28: while (ticks == jiffies)
29: /* nothing */;
30: ticks = jiffies;
31: __delay(loops_per_jiffy);
32: if (jiffies != ticks) /* longer than 1 tick */
33: loops_per_jiffy &= ~loopbit;
34: }
35:
36: pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
37: loops_per_jiffy/(500000/HZ),
38: (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
39: }
一開始定義的 LPS_PREC 8 代表是要算的精確度是多少,其實他代表的是要幾個bit的精確度。
概念就是他算出一個jiffy可以跑多少指令(loops_per_jiffy),然後一秒鐘有HZ個jiffy,所以最終答案就是 HZ*loops_per_jiffy。
函式分兩個段落,第一個段落是17行之前,算出一個jiffy最少需要幾個 2^N 個loops_per_jiffy,第一個段落會算出N的值。
下面舉個例子,程式會從 2^0, 2^1…到 2^4之後就會超過一個jiffy了。所以第一個段落我們會得到0b10000的值。所以代表
正確值會小於 0b10000 ,會大於 0b01000。
所以第二個段落就是要找出0b1xyz,中間那些xyz的值。程式的邏輯都事先假設一開始是1,所以先測試 0b1100,如果0b1100會超過一個jiffy的話,就代表x=0。如果不會的話,x=1,然後繼續檢查y。最後檢查到LPS_PREC=8個位數。
想通這個演算法之後,他其實是二分法,跑完第一階段之後,如果loops_per_jiffy=0b10000 = 16,那就代表最小值是8,最大值是15,所以先檢查 0b1100 = 12,接下來如果超過的話就檢查 0b1010 = 10,如果沒超過的話就是0b1110 = 14,剛好是中間值,太神奇了~
留言