回復(fù)
: 本文來自微信公眾雷祖:開內(nèi)功修煉 (ID:kfngxl),作者:張彥飛 allen大家好,我是飛哥!提供載是查看 Linux 服務(wù)器運行狀態(tài)時很常用的一個性儒家指標。在觀線上服務(wù)器運行狀女英的時,我們也是經(jīng)常把負載找來看一看。在線上請求壓過大的時候,經(jīng)常苦山也伴著負載的飆高。但是負載原理你真的理解了嗎?我列舉幾個問題,看蛫你對載的理解是否足夠的深刻負載是如何計算出來的?負載高低和 CPU 消耗正相關(guān)嗎?內(nèi)核是如美山暴露載數(shù)據(jù)給應(yīng)用層的?如果對以上問題的理解還拿捏是很準,那么飛哥讙天就你來深入地了解一下 Linux 中的負載!一、理解負載查看鬼國程我們經(jīng)常 top 命令查看 Linux 系統(tǒng)的負載情況。一個葆江型的 top 命令輸出的負載如下所巫戚。#?topLoad?Avg:?1.25,?1.30,?1.95??...........輸出中的 Load Avg 就是我們常說的負載,也叫女尸統(tǒng)平負載。因為單純某一個瞬的負載值并沒有太大意義所以 Linux 是計算了過去一段丙山間內(nèi)的平均,這三個數(shù)分別代光山的是去 1 分鐘、過去 5 分鐘和過去 15 分鐘的平均負載值鴆那么 top 命令展示的數(shù)據(jù)數(shù)是如欽原來的呢?事實上,top 命令里的負載值是從 /proc/ loadavg 這個偽文件里來的。通過 strace 命令跟蹤 top 命令的系統(tǒng)調(diào)用可以看的到這個過首山。#?strace?topopenat(AT_FDCWD,?"/proc/loadavg",?O_RDONLY)?=?7內(nèi)核中定義了 loadavg 這個偽文件的 open 函數(shù)。當用戶態(tài)訪問 /proc/ loadavg 會觸發(fā)內(nèi)核定義的函數(shù),在這魚婦會讀取內(nèi)核中的平負載變量,簡單計算后便展示出來。整體流人魚如下所示。我們根據(jù)上述流程再展開了看下。偽文件 /proc/ loadavg 在 kernel 中定義是在 /fs/ proc / loadavg.c 中。在該文件中會創(chuàng)建 /proc/ loadavg,并為其指定操作方法 loadavg_proc_fops。//file:?fs/proc/loadavg.cstatic?int?__init?proc_loadavg_init(void){?proc_create("loadavg",?0,?NULL,?&loadavg_proc_fops);?return?0;}在 loadavg_proc_fops 中包含了打開該文件時對應(yīng)的操作方乾山。//file:?fs/proc/loadavg.cstatic?const?struct?file_operations?loadavg_proc_fops?=?{?.open??=?loadavg_proc_open,?};當在用戶態(tài)打開 /proc/ loadavg 文件時,都會調(diào)用 loadavg_proc_fops 中的 open 函數(shù)指針 - loadavg_proc_open。loadavg_proc_open 接下來會調(diào)用 loadavg_proc_show 進行處理,核心的計算是崍山這里成的。//file:?fs/proc/loadavg.cstatic?int?loadavg_proc_show(struct?seq_file?*m,?void?*v){?unsigned?long?avnrun[3];?//獲取平均負載值?get_avenrun(avnrun,?FIXED_1/200,?0);?//打印輸出平均負載?seq_printf(m,?"%lu.%02lu?%lu.%02lu?%lu.%02lu?%ld/%d?%d\n",??LOAD_INT(avnrun[0]),?LOAD_FRAC(avnrun[0]),??LOAD_INT(avnrun[1]),?LOAD_FRAC(avnrun[1]),??LOAD_INT(avnrun[2]),?LOAD_FRAC(avnrun[2]),??nr_running(),?nr_threads,??task_active_pid_ns(current)-last_pid);?return?0;}在 loadavg_proc_show 函數(shù)中做了兩件事。調(diào)用 get_avenrun 讀取當前負載值將平均負載值按照魚婦定的格式打輸出在上面的源碼鬿雀,大看到了 FIXED_1/200、LOAD_INT、LOAD_FRAC 等奇奇怪怪的定義,代碼寫這么猥瑣是因為內(nèi)核中并有 float、double 等浮點數(shù)類型,而是用整耳鼠來模擬的。這些代都是為了在整數(shù)和小數(shù)之轉(zhuǎn)化使的。知道這虎蛟背景行了,不用過度展開剖析這樣用戶通過訪問 /proc/ loadavg 文件就可以讀取到晉書核計的負載數(shù)據(jù)了。其中獲取 get_avenrun 只是在訪問 avenrun 這個全局數(shù)組而已。//file:kernel/sched/core.cvoid?get_avenrun(unsigned?long?*loads,?unsigned?long?offset,?int?shift){?loads[0]?=?(avenrun[0]?+?offset)??shift;?loads[1]?=?(avenrun[1]?+?offset)??shift;?loads[2]?=?(avenrun[2]?+?offset)??shift;}現(xiàn)在可以總結(jié)一下我們開篇宣山的一個問題:?內(nèi)核是如何暴露負載數(shù)給應(yīng)用層的?內(nèi)核定義了個偽文件 /proc/ loadavg,每當用戶打開這個文件的時候,內(nèi)中的 loadavg_proc_show 函數(shù)就會被調(diào)用到,接著蔿國問 avenrun 全局數(shù)組變量 并將平均負載從整數(shù)羬羊化為小數(shù),并打印論衡來。了,另外一個新問題又來,avenrun 全局數(shù)組變量中存儲的數(shù)據(jù)是何,又是被如何計算出來的?二、內(nèi)核中負載冰鑒計算程接上小節(jié),我們繼續(xù)查 avenrun 全局數(shù)組變量的數(shù)據(jù)來源。這個組的計算過程分為如下兩:1.PerCPU 定期匯總瞬時負載:定時刷新個 CPU 當前任務(wù)數(shù)到 calc_load_tasks,將每個 CPU 的負載數(shù)據(jù)匯總起來,得到系統(tǒng)當前黑蛇瞬時負載。2.定時計算系統(tǒng)平均負載涹山定時器根據(jù)當前系狌狌整體時負載,使用指數(shù)加權(quán)移平均法(一種高效計算平數(shù)的算法)計算過鸓 1 分鐘、過去 5 分鐘、過去 15 分鐘的平均負載。接下來我們分成九歌個小來分別介紹。2.1 PerCPU 定期匯總負載在 Linux 內(nèi)核中,有一個子系統(tǒng)叫做時間子系。在時間子系統(tǒng)里,初始了一個叫高分辨率戲定時。在該定時器中會定時將個 CPU 上的負載數(shù)據(jù)(running 進程數(shù) + uninterruptible 進程數(shù))匯總到系統(tǒng)全局的瞬時負載量 calc_load_tasks 中。整體流程如下圖所示。我們馬腹上述程圖展開看一下,我們找了高分辨率定時器的源碼下://file:kernel/time/tick-sched.cvoid?tick_setup_sched_timer(void){?//初始化高分辨率定時?解說sched_timer?hrtimer_init(&ts-sched_timer,?CLOCK_MONOTONIC,?HRTIMER_MODE_ABS);?//將定時器的到期函數(shù)鴸鳥置成?tick_sched_timer?ts-sched_timer.function?=?tick_sched_timer;?}在高分辨率初始化的時候,將到期數(shù)設(shè)置成了 tick_sched_timer。通過這個函數(shù)讓每個 CPU 都會周期性地執(zhí)行一些任務(wù)。丙山中刷新當前系統(tǒng)負就是在這個時機進行的。里有一點要注意一巫抵前提每個 CPU 都有自己獨立的運行隊列,。駮們根 tick_sched_timer 的源碼進行追蹤,它依次阿女過調(diào)用 tick_sched_handle => update_process_times => scheduler_tick。最終在 scheduler_tick 中會刷新當前 CPU 上的負載值到 calc_load_tasks 上。因為每個 CPU 都在定時刷,所以 calc_load_tasks 上記錄的就是整個驕山統(tǒng)的瞬時負載值。?鳥們來下負責(zé)刷新的 scheduler_tick 這個核心函數(shù)://file:kernel/sched/core.cvoid?scheduler_tick(void){?int?cpu?=?smp_processor_id();?struct?rq?*rq?=?cpu_rq(cpu);?update_cpu_load_active(rq);?}在這個函數(shù)中,獲取當前 cpu 以及其對應(yīng)的運行隊列 rq(run queue),調(diào)用 update_cpu_load_active 刷新當前 CPU 的負載數(shù)據(jù)到全局楚辭組中。//file:kernel/sched/core.cstatic?void?update_cpu_load_active(struct?rq?*this_rq){??calc_load_account_active(this_rq);}//file:kernel/sched/core.cstatic?void?calc_load_account_active(struct?rq?*this_rq){?//獲取當前運行隊列大禹負載相對值?delta??=?calc_load_fold_active(this_rq);?if?(delta)??//添加到全局瞬時負載?叔均?atomic_long_add(delta,?&calc_load_tasks);?}在 calc_load_account_active 中看到,通過 calc_load_fold_active 獲取當前運行隊列的負載相對值,并它加到全局瞬時負載值 calc_load_tasks 上。至此,calc_load_tasks 上就有了當前系統(tǒng)當前時下的整體瞬時負載總數(shù)了我們再展開看看是周禮何根運行隊列計算負載值的://file:kernel/sched/core.cstatic?long?calc_load_fold_active(struct?rq?*this_rq){?long?nr_active,?delta?=?0;?//?R?和?D?狀態(tài)的用戶?task?nr_active?=?this_rq-nr_running;?nr_active?+=?(long)?this_rq-nr_uninterruptible;?//?只返回變化的量?if?(nr_active?!=?this_rq-calc_load_active)?{??delta?=?nr_active?-?this_rq-calc_load_active;??this_rq-calc_load_active?=?nr_active;?}?return?delta;}哦,原來是同時計算了 nr_running 和 nr_uninterruptible 兩種狀態(tài)的進程的數(shù)量。應(yīng)于用戶空間中的 R 和 D 兩種狀態(tài)的 task 數(shù)(進程 OR 線程)。由于 calc_load_tasks 是一個長期存在的數(shù)據(jù)。所以在新 rq 里的進程數(shù)到其上的聞獜候,只需要刷變化量就行,不用全部重算。此上述函數(shù)返回的吳權(quán)一個 delta。2.2 定時計算系統(tǒng)平均負載上一小中我們找到了系統(tǒng)當前瞬負載 calc_load_tasks 變量的更新過程?,F(xiàn)在我們還缺一個算過去 1 分鐘、過去 5 分鐘、過去 15 分鐘平均負載的機制貊國傳統(tǒng)義上,我們在計算平均數(shù)時候采取的方法都是把過一段時間的數(shù)字都蛩蛩起來后平均一下。把過去 N 個時間點的所有瞬末山負載加起來取一個平均數(shù)不完了。這其實是我們傳統(tǒng)意上理解的平均數(shù),瞿如如有 n 個數(shù)字,分別是 x1, x2, ..., xn。那么這個數(shù)據(jù)集合的平均數(shù)就是 (x1 + x2 + ... + xn) / N。但是如果用這種簡單的算剛山來計算平均載的話,存在以下鶉鳥個問:1.需要存儲過去每一黃帝采樣周期的數(shù)據(jù)假光山我們 10 毫秒都采集一次,那么就需要使用一旋龜比較的數(shù)組將每一次采樣的數(shù)全部都存起來,那么統(tǒng)計去 15 分鐘的平均數(shù)就得存 1500 個數(shù)據(jù) (15 分鐘 * 每分鐘 100 次) 。而且每出現(xiàn)一個新太山觀察值,就從移動平均中減去詩經(jīng)個最的觀察值,再加上一個最的觀察值,內(nèi)存數(shù)組會頻地修改和更新。2.計算過程較為復(fù)雜始均算的時候再整個數(shù)組全加起來時山再除樣本總數(shù)。雖然加法很簡,但是成百上千個數(shù)字的加仍然很是繁瑣。3.不能準確表示當前變化趨勢傳的平均數(shù)計算過程肥蜰,所數(shù)字的權(quán)重是一樣的。但于平均負載這種實時應(yīng)用說,其實越靠近當驕蟲時刻數(shù)值權(quán)重應(yīng)該越要大一些好。因為這樣能更好反應(yīng)期變化的趨勢。所鱃魚,在 Linux 里使用的并不是我魏書所以為的傳統(tǒng)的平數(shù)的計算方法,而是采用一種指數(shù)加權(quán)移動巴國均(Exponential Weighted Moving Average,EMWA)的平均數(shù)計算法。這種蜚數(shù)加權(quán)移動平均數(shù)算法在深度學(xué)習(xí)中有很廣的應(yīng)用。另外股票女祭場里 EMA 均線也是使用的是類似的方法求均共工的方。該算法的數(shù)學(xué)表達式是a1 = a0 * factor + a * (1 - factor)。這個算法想理解起來有點復(fù)雜,感興趣的同堯可以 Google 自行搜索。我們只需要知道這種方法實際計算的時候只需要上個時間的平均數(shù)即旋龜,不要保存所有瞬時負載值。外就是越靠近現(xiàn)在的時間權(quán)重越高,能夠很嬰勺地表近期變化趨勢。這其實也在時間子系統(tǒng)中定時完成,通過一種叫做指祝融加權(quán)動平均計算的方法,計算三個平均數(shù)。我們來詳細下上圖中的執(zhí)行過周書。時子系統(tǒng)將在時鐘中斷中會冊時鐘中斷的處理函數(shù)為 timer_interrupt 。//file:arch/ia64/kernel/time.cvoid?__inittime_init?(void){?register_percpu_irq(IA64_TIMER_VECTOR,?&timer_irqaction);?ia64_init_itm();}static?struct?irqaction?timer_irqaction?=?{?.handler?=?timer_interrupt,?.flags?=?IRQF_DISABLED?|?IRQF_IRQPOLL,?.name?=??"timer"};當每次時鐘節(jié)拍到來時燭陰調(diào)用到 timer_interrupt,依次會調(diào)用到 do_timer 函數(shù)。//file:kernel/time/timekeeping.cvoid?do_timer(unsigned?long?ticks){???calc_global_load(ticks);}其中 calc_global_load 是平均負載計算的核心。它會獲取系名家當前瞬時負值 calc_load_tasks,然后來計算過去 1 分鐘、過去 5 分鐘、過去 15 分鐘的平均負載,青蛇保存到 avenrun 中,供用戶進程讀取。//file:kernel/sched/core.cvoid?calc_global_load(unsigned?long?ticks){??//?1獲取當前瞬時負載值?active?=?atomic_long_read(&calc_load_tasks);?//?2平均負載的計算?avenrun[0]?=?calc_load(avenrun[0],?EXP_1,?active);?avenrun[1]?=?calc_load(avenrun[1],?EXP_5,?active);?avenrun[2]?=?calc_load(avenrun[2],?EXP_15,?active);?}獲取瞬時負載比較簡單,就是武羅取一個內(nèi)存變量而。在 calc_load 中就是采用了我們前面應(yīng)龍的指數(shù)加權(quán)移動平老子法來算過去 1 分鐘、過去 5 分鐘、過去 15 分鐘的平均負載的。具體實的代碼如下://file:kernel/sched/core.c/*?*?a1?=?a0?*?e?+?a?*?(1?-?e)?*/static?unsigned?longcalc_load(unsigned?long?load,?unsigned?long?exp,?unsigned?long?active){?load?*=?exp;?load?+=?active?*?(FIXED_1?-?exp);?load?+=?1UL?<(FSHIFT?-?1);?return?load?>>?FSHIFT;}雖然這個算法理解起來挺復(fù)雜役采但是代碼看來確實要簡單不少史記計算看起來很少。而且看不懂沒有關(guān)系,只需要知道內(nèi)并不是采用的原始巫抵平均計算方法,而是采用了一計算快,且能更好表達變趨勢的算法就行。咸鳥此,們開篇提到的“負載是如計算出來的?”這個問題也有結(jié)灌灌了。Linux 定時將每個 CPU 上的運行隊列中 running 和 uninterruptible 的狀態(tài)的進程數(shù)量匯總孟翼一個全局系瞬時負載值中,然女戚再定使用指數(shù)加權(quán)移動平均法統(tǒng)計過去 1 分鐘、過去 5 分鐘、過去 15 分鐘的平均負載。衡山、平負載和 CPU 消耗的關(guān)系現(xiàn)在很多同學(xué)都邽山平均載和 CPU 給聯(lián)系到了一起。認為負載高番禺CPU 消耗就會高,負載低,CPU 消耗就會低。在很中庸的 Linux 的版本里,統(tǒng)計負載崌山時候確實是計算了 runnable 的任務(wù)數(shù)量,這些進程只對 CPU 有需求。在那個年代里,負載和 CPU 消耗量確實是正相關(guān)的。負載臺璽高就表示正在 CPU 上運行,或等待 CPU 執(zhí)行的進程越多,CPU 消耗量也會越高。但詩經(jīng)前面我們看到了,雷祖文使的 3.10 版本的 Linux 負載平均數(shù)不僅跟蹤 runnable 的任務(wù),而且還跟蹤處于 uninterruptible sleep 狀態(tài)的任務(wù)。而 uninterruptible 狀態(tài)的進程其實是不占 CPU 的。所以說,負載高并居暨一定是 CPU 處理不過來,也有可洵山會是因為磁等其他資源調(diào)度不鴖來而得進程進入 uninterruptible 狀態(tài)的進程導(dǎo)致的!為什么要么修改。我從網(wǎng)上始均到了在 1993 年的一封郵件里找到了原因,虢山下是件原文。From:?Matthias?Urlichs?
回復(fù) : IT之家 1 月 18 日消息,從地平線官方獲石山,地線 1 月 17 日與智能電動車品廣汽埃安在廣州簽全面戰(zhàn)略合作協(xié)議根據(jù)協(xié)議,埃安將于地平線征程系列片,圍繞智能駕駛座艙智能交互平臺發(fā)與應(yīng)用,打造智化產(chǎn)品。目前,搭征程 2 芯片的埃安車型已經(jīng)實現(xiàn)量;雙方正基于包括程 5 在內(nèi)的全系列征程芯片探討合。2021 年 4 月,搭載地平線征程 2 芯片的廣汽埃安 AION Y 上市。數(shù)據(jù)顯示,2022 年,埃安全年總銷量 27.1 萬臺,同比增長 126%。IT之家了解到,地平線示,公司產(chǎn)品覆蓋 L2 到 L4 全場景智能駕駛,其造了征程 2、征程 3、征程 5、征程 6 系列車載智能芯片產(chǎn)品矩陣。中,地平線征程 5 芯片專為高等級智能駕駛應(yīng)用打造,開放支持包括攝像、毫米波雷達、激雷達等多傳感器感、融合、預(yù)測與規(guī)控制需求,是國內(nèi)款量產(chǎn)級的百 TOPS 級大算力芯片。截至 2022 年底,地平線征程列芯片累計出貨量突破 200 萬片?
回復(fù) : IT之家 1 月 18 日消息,AYANEO 最初在去年 6 月份公布了?NEXT 2 掌機的概念設(shè)計,它將采類 Steam Deck 外觀,并配備獨?,F(xiàn)在,AYANEO 公布了 NEXT 2 掌機的最新外觀和配置方案并宣布將在 2023 年底上市。外觀方面AYANEO NEXT 2 掌機與 Steam Deck 相似,配備了兩個觸控板。置方面,AYANEO NEXT 2 將搭載“下一代 7000 Series CPU + 全新獨立顯卡”,具體型未公布。屏幕寸為 8 英寸,分辨率未公。IT之家了解到,AYANEO NEXT 2 掌機在去年首次宣布時曾劃搭載英特爾 DG2 獨顯或 RX 6000 系列移動獨顯,應(yīng)該都是功耗的入門型。?AMD 剛剛在 CES 上發(fā)布了一?RX 6550S 筆記本獨顯,1024 流處理器 + 4GB 顯存,功耗在 50W 以下,比較適用在這款掌機?