chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CPU是如何調(diào)度任務(wù)的?

Linux愛好者 ? 來(lái)源:Linux愛好者 ? 作者:Linux愛好者 ? 2020-12-11 16:44 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

你清楚下面這幾個(gè)問(wèn)題嗎?

有了內(nèi)存,為什么還需要 CPU Cache?

CPU 是怎么讀寫數(shù)據(jù)的?

如何讓 CPU 能讀取數(shù)據(jù)更快一些?

CPU 偽共享是如何發(fā)生的?又該如何避免?

CPU 是如何調(diào)度任務(wù)的?如果你的任務(wù)對(duì)響應(yīng)要求很高,你希望它總是能被先調(diào)度,這該怎么辦?

這篇,我們就來(lái)回答這些問(wèn)題。

e445f548-28a5-11eb-a64d-12bb97331649.png

正文

CPU 如何讀寫數(shù)據(jù)的?

先來(lái)認(rèn)識(shí) CPU 的架構(gòu),只有理解了 CPU 的 架構(gòu),才能更好地理解 CPU 是如何讀寫數(shù)據(jù)的,對(duì)于現(xiàn)代 CPU 的架構(gòu)圖如下:

e48eff04-28a5-11eb-a64d-12bb97331649.png

可以看到,一個(gè) CPU 里通常會(huì)有多個(gè) CPU 核心,比如上圖中的 1 號(hào)和 2 號(hào) CPU 核心,并且每個(gè) CPU 核心都有自己的 L1 Cache 和 L2 Cache,而 L1 Cache 通常分為 dCache(數(shù)據(jù)緩存) 和 iCache(指令緩存),L3 Cache 則是多個(gè)核心共享的,這就是 CPU 典型的緩存層次。

上面提到的都是 CPU 內(nèi)部的 Cache,放眼外部的話,還會(huì)有內(nèi)存和硬盤,這些存儲(chǔ)設(shè)備共同構(gòu)成了金字塔存儲(chǔ)層次。如下圖所示:

e4d1cdf2-28a5-11eb-a64d-12bb97331649.png

從上圖也可以看到,從上往下,存儲(chǔ)設(shè)備的容量會(huì)越大,而訪問(wèn)速度會(huì)越慢。至于每個(gè)存儲(chǔ)設(shè)備的訪問(wèn)延時(shí),你可以看下圖的表格:

e504a0f6-28a5-11eb-a64d-12bb97331649.png

你可以看到, CPU 訪問(wèn) L1 Cache 速度比訪問(wèn)內(nèi)存快 100 倍,這就是為什么 CPU 里會(huì)有 L1~L3 Cache 的原因,目的就是把 Cache 作為 CPU 與內(nèi)存之間的緩存層,以減少對(duì)內(nèi)存的訪問(wèn)頻率。

CPU 從內(nèi)存中讀取數(shù)據(jù)到 Cache 的時(shí)候,并不是一個(gè)字節(jié)一個(gè)字節(jié)讀取,而是一塊一塊的方式來(lái)讀取數(shù)據(jù)的,這一塊一塊的數(shù)據(jù)被稱為 CPU Line(緩存行),所以CPU Line 是 CPU 從內(nèi)存讀取數(shù)據(jù)到 Cache 的單位。

至于 CPU Line 大小,在 Linux 系統(tǒng)可以用下面的方式查看到,你可以看我服務(wù)器的 L1 Cache Line 大小是 64 字節(jié),也就意味著L1 Cache 一次載入數(shù)據(jù)的大小是 64 字節(jié)。

e51c0a02-28a5-11eb-a64d-12bb97331649.png

那么對(duì)數(shù)組的加載, CPU 就會(huì)加載數(shù)組里面連續(xù)的多個(gè)數(shù)據(jù)到 Cache 里,因此我們應(yīng)該按照物理內(nèi)存地址分布的順序去訪問(wèn)元素,這樣訪問(wèn)數(shù)組元素的時(shí)候,Cache 命中率就會(huì)很高,于是就能減少?gòu)膬?nèi)存讀取數(shù)據(jù)的頻率, 從而可提高程序的性能。

但是,在我們不使用數(shù)組,而是使用單獨(dú)的變量的時(shí)候,則會(huì)有 Cache 偽共享的問(wèn)題,Cache 偽共享問(wèn)題上是一個(gè)性能殺手,我們應(yīng)該要規(guī)避它。

接下來(lái),就來(lái)看看 Cache 偽共享是什么?又如何避免這個(gè)問(wèn)題?

現(xiàn)在假設(shè)有一個(gè)雙核心的 CPU,這兩個(gè) CPU 核心并行運(yùn)行著兩個(gè)不同的線程,它們同時(shí)從內(nèi)存中讀取兩個(gè)不同的數(shù)據(jù),分別是類型為long的變量 A 和 B,這個(gè)兩個(gè)數(shù)據(jù)的地址在物理內(nèi)存上是連續(xù)的,如果 Cahce Line 的大小是 64 字節(jié),并且變量 A 在 Cahce Line 的開頭位置,那么這兩個(gè)數(shù)據(jù)是位于同一個(gè) Cache Line 中,又因?yàn)?CPU Line 是 CPU 從內(nèi)存讀取數(shù)據(jù)到 Cache 的單位,所以這兩個(gè)數(shù)據(jù)會(huì)被同時(shí)讀入到了兩個(gè) CPU 核心中各自 Cache 中。

e55ae862-28a5-11eb-a64d-12bb97331649.png

我們來(lái)思考一個(gè)問(wèn)題,如果這兩個(gè)不同核心的線程分別修改不同的數(shù)據(jù),比如 1 號(hào) CPU 核心的線程只修改了 變量 A,或 2 號(hào) CPU 核心的線程的線程只修改了變量 B,會(huì)發(fā)生什么呢?

分析偽共享的問(wèn)題

現(xiàn)在我們結(jié)合保證多核緩存一致的 MESI 協(xié)議,來(lái)說(shuō)明這一整個(gè)的過(guò)程,如果你還不知道 MESI 協(xié)議,你可以看我這篇文章「10 張圖打開 CPU 緩存一致性的大門」。

①. 最開始變量 A 和 B 都還不在 Cache 里面,假設(shè) 1 號(hào)核心綁定了線程 A,2 號(hào)核心綁定了線程 B,線程 A 只會(huì)讀寫變量 A,線程 B 只會(huì)讀寫變量 B。

e59854d6-28a5-11eb-a64d-12bb97331649.png

②. 1 號(hào)核心讀取變量 A,由于 CPU 從內(nèi)存讀取數(shù)據(jù)到 Cache 的單位是 Cache Line,也正好變量 A 和 變量 B 的數(shù)據(jù)歸屬于同一個(gè) Cache Line,所以 A 和 B 的數(shù)據(jù)都會(huì)被加載到 Cache,并將此 Cache Line 標(biāo)記為「獨(dú)占」?fàn)顟B(tài)。

e5d26676-28a5-11eb-a64d-12bb97331649.png

③. 接著,2 號(hào)核心開始從內(nèi)存里讀取變量 B,同樣的也是讀取 Cache Line 大小的數(shù)據(jù)到 Cache 中,此 Cache Line 中的數(shù)據(jù)也包含了變量 A 和 變量 B,此時(shí) 1 號(hào)和 2 號(hào)核心的 Cache Line 狀態(tài)變?yōu)椤腹蚕怼範(fàn)顟B(tài)。

e612d38c-28a5-11eb-a64d-12bb97331649.png

④. 1 號(hào)核心需要修改變量 A,發(fā)現(xiàn)此 Cache Line 的狀態(tài)是「共享」?fàn)顟B(tài),所以先需要通過(guò)總線發(fā)送消息給 2 號(hào)核心,通知 2 號(hào)核心把 Cache 中對(duì)應(yīng)的 Cache Line 標(biāo)記為「已失效」?fàn)顟B(tài),然后 1 號(hào)核心對(duì)應(yīng)的 Cache Line 狀態(tài)變成「已修改」?fàn)顟B(tài),并且修改變量 A。

e63cd4f2-28a5-11eb-a64d-12bb97331649.png

⑤. 之后,2 號(hào)核心需要修改變量 B,此時(shí) 2 號(hào)核心的 Cache 中對(duì)應(yīng)的 Cache Line 是已失效狀態(tài),另外由于 1 號(hào)核心的 Cache 也有此相同的數(shù)據(jù),且狀態(tài)為「已修改」?fàn)顟B(tài),所以要先把 1 號(hào)核心的 Cache 對(duì)應(yīng)的 Cache Line 寫回到內(nèi)存,然后 2 號(hào)核心再?gòu)膬?nèi)存讀取 Cache Line 大小的數(shù)據(jù)到 Cache 中,最后把變量 B 修改到 2 號(hào)核心的 Cache 中,并將狀態(tài)標(biāo)記為「已修改」?fàn)顟B(tài)。

e65e7f8a-28a5-11eb-a64d-12bb97331649.png

所以,可以發(fā)現(xiàn)如果 1 號(hào)和 2 號(hào) CPU 核心這樣持續(xù)交替的分別修改變量 A 和 B,就會(huì)重復(fù) ④ 和 ⑤ 這兩個(gè)步驟,Cache 并沒(méi)有起到緩存的效果,雖然變量 A 和 B 之間其實(shí)并沒(méi)有任何的關(guān)系,但是因?yàn)橥瑫r(shí)歸屬于一個(gè) Cache Line ,這個(gè) Cache Line 中的任意數(shù)據(jù)被修改后,都會(huì)相互影響,從而出現(xiàn) ④ 和 ⑤ 這兩個(gè)步驟。

因此,這種因?yàn)槎鄠€(gè)線程同時(shí)讀寫同一個(gè) Cache Line 的不同變量時(shí),而導(dǎo)致 CPU Cache 失效的現(xiàn)象稱為偽共享(False Sharing)。

避免偽共享的方法

因此,對(duì)于多個(gè)線程共享的熱點(diǎn)數(shù)據(jù),即經(jīng)常會(huì)修改的數(shù)據(jù),應(yīng)該避免這些數(shù)據(jù)剛好在同一個(gè) Cache Line 中,否則就會(huì)出現(xiàn)為偽共享的問(wèn)題。

接下來(lái),看看在實(shí)際項(xiàng)目中是用什么方式來(lái)避免偽共享的問(wèn)題的。

在 Linux 內(nèi)核中存在__cacheline_aligned_in_smp宏定義,是用于解決偽共享的問(wèn)題。

從上面的宏定義,我們可以看到:

如果在多核(MP)系統(tǒng)里,該宏定義是__cacheline_aligned,也就是 Cache Line 的大?。?/p>

而如果在單核系統(tǒng)里,該宏定義是空的;

因此,針對(duì)在同一個(gè) Cache Line 中的共享的數(shù)據(jù),如果在多核之間競(jìng)爭(zhēng)比較嚴(yán)重,為了防止偽共享現(xiàn)象的發(fā)生,可以采用上面的宏定義使得變量在 Cache Line 里是對(duì)齊的。

舉個(gè)例子,有下面這個(gè)結(jié)構(gòu)體:

結(jié)構(gòu)體里的兩個(gè)成員變量 a 和 b 在物理內(nèi)存地址上是連續(xù)的,于是它們可能會(huì)位于同一個(gè) Cache Line 中,如下圖:

e72b5b54-28a5-11eb-a64d-12bb97331649.png

所以,為了防止前面提到的 Cache 偽共享問(wèn)題,我們可以使用上面介紹的宏定義,將 b 的地址設(shè)置為 Cache Line 對(duì)齊地址,如下:

e7457656-28a5-11eb-a64d-12bb97331649.png

這樣 a 和 b 變量就不會(huì)在同一個(gè) Cache Line 中了,如下圖:

e77fe6a6-28a5-11eb-a64d-12bb97331649.png

所以,避免 Cache 偽共享實(shí)際上是用空間換時(shí)間的思想,浪費(fèi)一部分 Cache 空間,從而換來(lái)性能的提升。

我們?cè)賮?lái)看一個(gè)應(yīng)用層面的規(guī)避方案,有一個(gè) Java 并發(fā)框架 Disruptor 使用「字節(jié)填充 + 繼承」的方式,來(lái)避免偽共享的問(wèn)題。

Disruptor 中有一個(gè) RingBuffer 類會(huì)經(jīng)常被多個(gè)線程使用,代碼如下:

e7a75f9c-28a5-11eb-a64d-12bb97331649.png

你可能會(huì)覺(jué)得 RingBufferPad 類里 7 個(gè) long 類型的名字很奇怪,但事實(shí)上,它們雖然看起來(lái)毫無(wú)作用,但卻對(duì)性能的提升起到了至關(guān)重要的作用。

我們都知道,CPU Cache 從內(nèi)存讀取數(shù)據(jù)的單位是 CPU Line,一般 64 位 CPU 的 CPU Line 的大小是 64 個(gè)字節(jié),一個(gè) long 類型的數(shù)據(jù)是 8 個(gè)字節(jié),所以 CPU 一下會(huì)加載 8 個(gè) long 類型的數(shù)據(jù)。

根據(jù) JVM 對(duì)象繼承關(guān)系中父類成員和子類成員,內(nèi)存地址是連續(xù)排列布局的,因此 RingBufferPad 中的 7 個(gè) long 類型數(shù)據(jù)作為 Cache Line前置填充,而 RingBuffer 中的 7 個(gè) long 類型數(shù)據(jù)則作為 Cache Line后置填充,這 14 個(gè) long 變量沒(méi)有任何實(shí)際用途,更不會(huì)對(duì)它們進(jìn)行讀寫操作。

e7e347f0-28a5-11eb-a64d-12bb97331649.png

另外,RingBufferFelds 里面定義的這些變量都是final修飾的,意味著第一次加載之后不會(huì)再修改, 又由于「前后」各填充了 7 個(gè)不會(huì)被讀寫的 long 類型變量,所以無(wú)論怎么加載 Cache Line,這整個(gè) Cache Line 里都沒(méi)有會(huì)發(fā)生更新操作的數(shù)據(jù),于是只要數(shù)據(jù)被頻繁地讀取訪問(wèn),就自然沒(méi)有數(shù)據(jù)被換出 Cache 的可能,也因此不會(huì)產(chǎn)生偽共享的問(wèn)題。

CPU 如何選擇線程的?

了解完 CPU 讀取數(shù)據(jù)的過(guò)程后,我們?cè)賮?lái)看看 CPU 是根據(jù)什么來(lái)選擇當(dāng)前要執(zhí)行的線程。

在 Linux 內(nèi)核中,進(jìn)程和線程都是用tark_struct結(jié)構(gòu)體表示的,區(qū)別在于線程的 tark_struct 結(jié)構(gòu)體里部分資源是共享了進(jìn)程已創(chuàng)建的資源,比如內(nèi)存地址空間、代碼段、文件描述符等,所以 Linux 中的線程也被稱為輕量級(jí)進(jìn)程,因?yàn)榫€程的 tark_struct 相比進(jìn)程的 tark_struct 承載的 資源比較少,因此以「輕」得名。

一般來(lái)說(shuō),沒(méi)有創(chuàng)建線程的進(jìn)程,是只有單個(gè)執(zhí)行流,它被稱為是主線程。如果想讓進(jìn)程處理更多的事情,可以創(chuàng)建多個(gè)線程分別去處理,但不管怎么樣,它們對(duì)應(yīng)到內(nèi)核里都是tark_struct。

e86efd0e-28a5-11eb-a64d-12bb97331649.png

所以,Linux 內(nèi)核里的調(diào)度器,調(diào)度的對(duì)象就是tark_struct,接下來(lái)我們就把這個(gè)數(shù)據(jù)結(jié)構(gòu)統(tǒng)稱為任務(wù)。

在 Linux 系統(tǒng)中,根據(jù)任務(wù)的優(yōu)先級(jí)以及響應(yīng)要求,主要分為兩種,其中優(yōu)先級(jí)的數(shù)值越小,優(yōu)先級(jí)越高:

實(shí)時(shí)任務(wù),對(duì)系統(tǒng)的響應(yīng)時(shí)間要求很高,也就是要盡可能快的執(zhí)行實(shí)時(shí)任務(wù),優(yōu)先級(jí)在0~99范圍內(nèi)的就算實(shí)時(shí)任務(wù);

普通任務(wù),響應(yīng)時(shí)間沒(méi)有很高的要求,優(yōu)先級(jí)在100~139范圍內(nèi)都是普通任務(wù)級(jí)別;

調(diào)度類

由于任務(wù)有優(yōu)先級(jí)之分,Linux 系統(tǒng)為了保障高優(yōu)先級(jí)的任務(wù)能夠盡可能早的被執(zhí)行,于是分為了這幾種調(diào)度類,如下圖:

e8965642-28a5-11eb-a64d-12bb97331649.png

Deadline 和 Realtime 這兩個(gè)調(diào)度類,都是應(yīng)用于實(shí)時(shí)任務(wù)的,這兩個(gè)調(diào)度類的調(diào)度策略合起來(lái)共有這三種,它們的作用如下:

SCHED_DEADLINE:是按照 deadline 進(jìn)行調(diào)度的,距離當(dāng)前時(shí)間點(diǎn)最近的 deadline 的任務(wù)會(huì)被優(yōu)先調(diào)度;

SCHED_FIFO:對(duì)于相同優(yōu)先級(jí)的任務(wù),按先來(lái)先服務(wù)的原則,但是優(yōu)先級(jí)更高的任務(wù),可以搶占低優(yōu)先級(jí)的任務(wù),也就是優(yōu)先級(jí)高的可以「插隊(duì)」;

SCHED_RR:對(duì)于相同優(yōu)先級(jí)的任務(wù),輪流著運(yùn)行,每個(gè)任務(wù)都有一定的時(shí)間片,當(dāng)用完時(shí)間片的任務(wù)會(huì)被放到隊(duì)列尾部,以保證相同優(yōu)先級(jí)任務(wù)的公平性,但是高優(yōu)先級(jí)的任務(wù)依然可以搶占低優(yōu)先級(jí)的任務(wù);

而 Fair 調(diào)度類是應(yīng)用于普通任務(wù),都是由 CFS 調(diào)度器管理的,分為兩種調(diào)度策略:

SCHED_NORMAL:普通任務(wù)使用的調(diào)度策略;

SCHED_BATCH:后臺(tái)任務(wù)的調(diào)度策略,不和終端進(jìn)行交互,因此在不影響其他需要交互的任務(wù),可以適當(dāng)降低它的優(yōu)先級(jí)。

完全公平調(diào)度

我們平日里遇到的基本都是普通任務(wù),對(duì)于普通任務(wù)來(lái)說(shuō),公平性最重要,在 Linux 里面,實(shí)現(xiàn)了一個(gè)基于 CFS 的調(diào)度算法,也就是完全公平調(diào)度(Completely Fair Scheduling)。

這個(gè)算法的理念是想讓分配給每個(gè)任務(wù)的 CPU 時(shí)間是一樣,于是它為每個(gè)任務(wù)安排一個(gè)虛擬運(yùn)行時(shí)間 vruntime,如果一個(gè)任務(wù)在運(yùn)行,其運(yùn)行的越久,該任務(wù)的 vruntime 自然就會(huì)越大,而沒(méi)有被運(yùn)行的任務(wù),vruntime 是不會(huì)變化的。

那么,在 CFS 算法調(diào)度的時(shí)候,會(huì)優(yōu)先選擇 vruntime 少的任務(wù),以保證每個(gè)任務(wù)的公平性。

這就好比,讓你把一桶的奶茶平均分到 10 杯奶茶杯里,你看著哪杯奶茶少,就多倒一些;哪個(gè)多了,就先不倒,這樣經(jīng)過(guò)多輪操作,雖然不能保證每杯奶茶完全一樣多,但至少是公平的。

當(dāng)然,上面提到的例子沒(méi)有考慮到優(yōu)先級(jí)的問(wèn)題,雖然是普通任務(wù),但是普通任務(wù)之間還是有優(yōu)先級(jí)區(qū)分的,所以在計(jì)算虛擬運(yùn)行時(shí)間 vruntime 還要考慮普通任務(wù)的權(quán)重值,注意權(quán)重值并不是優(yōu)先級(jí)的值,內(nèi)核中會(huì)有一個(gè) nice 級(jí)別與權(quán)重值的轉(zhuǎn)換表,nice 級(jí)別越低的權(quán)重值就越大,至于 nice 值是什么,我們后面會(huì)提到。
于是就有了以下這個(gè)公式:

e8d81cee-28a5-11eb-a64d-12bb97331649.png

你可以不用管 NICE_0_LOAD 是什么,你就認(rèn)為它是一個(gè)常量,那么在「同樣的實(shí)際運(yùn)行時(shí)間」里,高權(quán)重任務(wù)的 vruntime 比低權(quán)重任務(wù)的 vruntime少,你可能會(huì)奇怪為什么是少的?你還記得 CFS 調(diào)度嗎,它是會(huì)優(yōu)先選擇 vruntime 少的任務(wù)進(jìn)行調(diào)度,所以高權(quán)重的任務(wù)就會(huì)被優(yōu)先調(diào)度了,于是高權(quán)重的獲得的實(shí)際運(yùn)行時(shí)間自然就多了。

CPU 運(yùn)行隊(duì)列

一個(gè)系統(tǒng)通常都會(huì)運(yùn)行著很多任務(wù),多任務(wù)的數(shù)量基本都是遠(yuǎn)超 CPU 核心數(shù)量,因此這時(shí)候就需要排隊(duì)。

事實(shí)上,每個(gè) CPU 都有自己的運(yùn)行隊(duì)列(Run Queue, rq),用于描述在此 CPU 上所運(yùn)行的所有進(jìn)程,其隊(duì)列包含三個(gè)運(yùn)行隊(duì)列,Deadline 運(yùn)行隊(duì)列 dl_rq、實(shí)時(shí)任務(wù)運(yùn)行隊(duì)列 rt_rq 和 CFS 運(yùn)行隊(duì)列 csf_rq,其中 csf_rq 是用紅黑樹來(lái)描述的,按 vruntime 大小來(lái)排序的,最左側(cè)的葉子節(jié)點(diǎn),就是下次會(huì)被調(diào)度的任務(wù)。

e8fcec40-28a5-11eb-a64d-12bb97331649.png

這幾種調(diào)度類是有優(yōu)先級(jí)的,優(yōu)先級(jí)如下:Deadline > Realtime > Fair,這意味著 Linux 選擇下一個(gè)任務(wù)執(zhí)行的時(shí)候,會(huì)按照此優(yōu)先級(jí)順序進(jìn)行選擇,也就是說(shuō)先從dl_rq里選擇任務(wù),然后從rt_rq里選擇任務(wù),最后從csf_rq里選擇任務(wù)。因此,實(shí)時(shí)任務(wù)總是會(huì)比普通任務(wù)優(yōu)先被執(zhí)行。

調(diào)整優(yōu)先級(jí)

如果我們啟動(dòng)任務(wù)的時(shí)候,沒(méi)有特意去指定優(yōu)先級(jí)的話,默認(rèn)情況下都是普通任務(wù),普通任務(wù)的調(diào)度類是 Fail,由 CFS 調(diào)度器來(lái)進(jìn)行管理。CFS 調(diào)度器的目的是實(shí)現(xiàn)任務(wù)運(yùn)行的公平性,也就是保障每個(gè)任務(wù)的運(yùn)行的時(shí)間是差不多的。

如果你想讓某個(gè)普通任務(wù)有更多的執(zhí)行時(shí)間,可以調(diào)整任務(wù)的nice值,從而讓優(yōu)先級(jí)高一些的任務(wù)執(zhí)行更多時(shí)間。nice 的值能設(shè)置的范圍是-20~19, 值越低,表明優(yōu)先級(jí)越高,因此 -20 是最高優(yōu)先級(jí),19 則是最低優(yōu)先級(jí),默認(rèn)優(yōu)先級(jí)是 0。

是不是覺(jué)得 nice 值的范圍很詭異?事實(shí)上,nice 值并不是表示優(yōu)先級(jí),而是表示優(yōu)先級(jí)的修正數(shù)值,它與優(yōu)先級(jí)(priority)的關(guān)系是這樣的:priority(new) = priority(old) + nice。內(nèi)核中,priority 的范圍是 0~139,值越低,優(yōu)先級(jí)越高,其中前面的 0~99 范圍是提供給實(shí)時(shí)任務(wù)使用的,而 nice 值是映射到 100~139,這個(gè)范圍是提供給普通任務(wù)用的,因此 nice 值調(diào)整的是普通任務(wù)的優(yōu)先級(jí)。

e93a3d66-28a5-11eb-a64d-12bb97331649.png

在前面我們提到了,權(quán)重值與 nice 值的關(guān)系的,nice 值越低,權(quán)重值就越大,計(jì)算出來(lái)的 vruntime 就會(huì)越少,由于 CFS 算法調(diào)度的時(shí)候,就會(huì)優(yōu)先選擇 vruntime 少的任務(wù)進(jìn)行執(zhí)行,所以 nice 值越低,任務(wù)的優(yōu)先級(jí)就越高。

我們可以在啟動(dòng)任務(wù)的時(shí)候,可以指定 nice 的值,比如將 mysqld 以 -3 優(yōu)先級(jí):

如果想修改已經(jīng)運(yùn)行中的任務(wù)的優(yōu)先級(jí),則可以使用renice來(lái)調(diào)整 nice 值:

nice 調(diào)整的是普通任務(wù)的優(yōu)先級(jí),所以不管怎么縮小 nice 值,任務(wù)永遠(yuǎn)都是普通任務(wù),如果某些任務(wù)要求實(shí)時(shí)性比較高,那么你可以考慮改變?nèi)蝿?wù)的優(yōu)先級(jí)以及調(diào)度策略,使得它變成實(shí)時(shí)任務(wù),比如:

總結(jié)

理解 CPU 是如何讀寫數(shù)據(jù)的前提,是要理解 CPU 的架構(gòu),CPU 內(nèi)部的多個(gè) Cache + 外部的內(nèi)存和磁盤都就構(gòu)成了金字塔的存儲(chǔ)器結(jié)構(gòu),在這個(gè)金字塔中,越往下,存儲(chǔ)器的容量就越大,但訪問(wèn)速度就會(huì)小。

CPU 讀寫數(shù)據(jù)的時(shí)候,并不是按一個(gè)一個(gè)字節(jié)為單位來(lái)進(jìn)行讀寫,而是以 CPU Line 大小為單位,CPU Line 大小一般是 64 個(gè)字節(jié),也就意味著 CPU 讀寫數(shù)據(jù)的時(shí)候,每一次都是以 64 字節(jié)大小為一塊進(jìn)行操作。

因此,如果我們操作的數(shù)據(jù)是數(shù)組,那么訪問(wèn)數(shù)組元素的時(shí)候,按內(nèi)存分布的地址順序進(jìn)行訪問(wèn),這樣能充分利用到 Cache,程序的性能得到提升。但如果操作的數(shù)據(jù)不是數(shù)組,而是普通的變量,并在多核 CPU 的情況下,我們還需要避免 Cache Line 偽共享的問(wèn)題。

所謂的 Cache Line 偽共享問(wèn)題就是,多個(gè)線程同時(shí)讀寫同一個(gè) Cache Line 的不同變量時(shí),而導(dǎo)致 CPU Cache 失效的現(xiàn)象。那么對(duì)于多個(gè)線程共享的熱點(diǎn)數(shù)據(jù),即經(jīng)常會(huì)修改的數(shù)據(jù),應(yīng)該避免這些數(shù)據(jù)剛好在同一個(gè) Cache Line 中,避免的方式一般有 Cache Line 大小字節(jié)對(duì)齊,以及字節(jié)填充等方法。

系統(tǒng)中需要運(yùn)行的多線程數(shù)一般都會(huì)大于 CPU 核心,這樣就會(huì)導(dǎo)致線程排隊(duì)等待 CPU,這可能會(huì)產(chǎn)生一定的延時(shí),如果我們的任務(wù)對(duì)延時(shí)容忍度很低,則可以通過(guò)一些人為手段干預(yù) Linux 的默認(rèn)調(diào)度策略和優(yōu)先級(jí)。

責(zé)任編輯:lq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11256

    瀏覽量

    224124
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7328

    瀏覽量

    94408
  • 存儲(chǔ)設(shè)備
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    19659

原文標(biāo)題:你不好奇 CPU 是如何執(zhí)行任務(wù)的?

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    一文說(shuō)透了如何實(shí)現(xiàn)單片機(jī)的多任務(wù)并發(fā)!

    任務(wù)并發(fā)。 一、任務(wù)調(diào)度 任務(wù)調(diào)度是多任務(wù)并發(fā)中一個(gè)非常重要的概念。它指的是如何在系統(tǒng)中組織和
    發(fā)表于 01-06 06:46

    國(guó)內(nèi)七大基于大模型的發(fā)射任務(wù)調(diào)度與過(guò)程保障分系統(tǒng)軟件介紹

    ? ? 七大基于大模型的發(fā)射任務(wù)調(diào)度與過(guò)程保障系統(tǒng) ? ?結(jié)合公開航天資料、機(jī)構(gòu)技術(shù)路線及商業(yè)航天實(shí)踐,可梳理出涵蓋國(guó)內(nèi)外典型案例的七大智能發(fā)射調(diào)度系統(tǒng)及平臺(tái)。這些系統(tǒng)深度融合大語(yǔ)言模型(LLM
    的頭像 發(fā)表于 12-24 11:08 ?219次閱讀

    基于大模型的發(fā)射任務(wù)調(diào)度與過(guò)程保障分系統(tǒng)平臺(tái)的應(yīng)用與未來(lái)發(fā)展

    ? ? 基于大模型的發(fā)射任務(wù)調(diào)度與過(guò)程保障分系統(tǒng)航天智能化升級(jí)核心方案 ? ?北京華盛恒輝大模型的發(fā)射任務(wù)調(diào)度與過(guò)程保障分系統(tǒng),是航天領(lǐng)域智能化升級(jí)的核心支撐。該系統(tǒng)憑借多源數(shù)據(jù)融合、
    的頭像 發(fā)表于 12-24 10:36 ?212次閱讀

    深入Linux內(nèi)核:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    在Linux系統(tǒng)中,進(jìn)程調(diào)度就像一位精明的“CPU管理員”——它決定著哪個(gè)進(jìn)程能優(yōu)先使用CPU,多久切換一次進(jìn)程,如何平衡系統(tǒng)響應(yīng)速度與資源利用率。小到桌面應(yīng)用的流暢點(diǎn)擊,大到服務(wù)器的多任務(wù)
    的頭像 發(fā)表于 12-24 07:05 ?3721次閱讀
    深入Linux內(nèi)核:進(jìn)程<b class='flag-5'>調(diào)度</b>的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    大模型驅(qū)動(dòng)的發(fā)射任務(wù)智能調(diào)度分系統(tǒng)軟件平臺(tái)的應(yīng)用與未來(lái)發(fā)展

    大模型驅(qū)動(dòng)的發(fā)射任務(wù)智能調(diào)度分系統(tǒng)平臺(tái) ? ?作為航天智能化轉(zhuǎn)型的關(guān)鍵支撐,該平臺(tái)融合多源數(shù)據(jù)、動(dòng)態(tài)資源調(diào)度與大模型智能決策能力,顯著提升發(fā)射任務(wù)的效率、安全性與可靠性。以下從技術(shù)架構(gòu)
    的頭像 發(fā)表于 12-19 14:50 ?252次閱讀

    大模型ai驅(qū)動(dòng)的發(fā)射任務(wù)智能調(diào)度分系統(tǒng):功能特點(diǎn)與平臺(tái)架構(gòu)解析

    ? ? 大模型AI驅(qū)動(dòng)的發(fā)射任務(wù)智能調(diào)度分系統(tǒng):航天智能化核心技術(shù)解析 ? ?北京華盛恒輝大模型AI驅(qū)動(dòng)的發(fā)射任務(wù)智能調(diào)度分系統(tǒng)作為航天領(lǐng)域智能化升級(jí)的關(guān)鍵支撐,通過(guò)多源數(shù)據(jù)整合、動(dòng)態(tài)
    的頭像 發(fā)表于 12-19 14:10 ?369次閱讀

    嵌入式基礎(chǔ)知識(shí)-系統(tǒng)調(diào)度

    得不到CPU的使用權(quán),也不會(huì)參與調(diào)度,除非它從掛起態(tài)中解除。 9 把一個(gè)掛起狀態(tài)的任務(wù)恢復(fù)的唯一途徑就是調(diào)用vTaskResume()或vTaskResumeFromISR() API函數(shù),如果此時(shí)被
    發(fā)表于 12-16 08:15

    在多任務(wù)系統(tǒng)中,如何平衡任務(wù)調(diào)度以防止因高負(fù)載導(dǎo)致的再次進(jìn)入低功耗模式的延遲?

    在多任務(wù)系統(tǒng)中,如何平衡任務(wù)調(diào)度以防止因高負(fù)載導(dǎo)致的再次進(jìn)入低功耗模式的延遲?
    發(fā)表于 12-04 06:37

    freertos關(guān)閉任務(wù)調(diào)度的方法

    #include \"FreeRTOS.h\" #include \"task.h\" /* 關(guān)閉任務(wù)調(diào)度 */ void
    發(fā)表于 11-17 06:47

    FreeRTOS任務(wù)調(diào)度及優(yōu)先級(jí)問(wèn)題

    大家好,最近本人在學(xué)習(xí)FreeRTOS ,之前有過(guò)一些裸機(jī)開發(fā)的經(jīng)驗(yàn),目前知道了FreeRTOS的任務(wù)是基于時(shí)間片輪轉(zhuǎn)來(lái)調(diào)度,也就是知道了任務(wù)會(huì)基于各個(gè)時(shí)間片來(lái)運(yùn)行。 于是聯(lián)想了如果有一些外設(shè)芯片
    發(fā)表于 11-06 02:18

    deepin社區(qū)開發(fā)者聯(lián)合打造CPU頻率調(diào)度

    你是否遇到過(guò) Linux 系統(tǒng)在高負(fù)載下突然卡死、發(fā)熱嚴(yán)重,甚至直接關(guān)機(jī)的情況?尤其是在一些老舊設(shè)備上,默認(rèn)的性能調(diào)度策略往往過(guò)于“激進(jìn)”,只要稍有負(fù)載,CPU 立刻飆到最高頻率——電耗得飛快,機(jī)器燙得嚇人,系統(tǒng)穩(wěn)定性也大打折扣。
    的頭像 發(fā)表于 09-12 10:54 ?999次閱讀
    deepin社區(qū)開發(fā)者聯(lián)合打造<b class='flag-5'>CPU</b>頻率<b class='flag-5'>調(diào)度</b>器

    揭秘!基于RT-Thread探究“優(yōu)先級(jí)反轉(zhuǎn)”下的任務(wù)調(diào)度究竟是什么樣的?| 技術(shù)集結(jié)

    本文將基于RT-Thread,結(jié)合RT-Trace調(diào)試器細(xì)化到實(shí)際任務(wù)調(diào)度的粒度,來(lái)調(diào)試并逐步講解“優(yōu)先級(jí)反轉(zhuǎn)”的調(diào)度和運(yùn)行邏輯。如果對(duì)RT-Trace感興趣的可以看這篇文章:國(guó)產(chǎn)嵌入式調(diào)試器之光
    的頭像 發(fā)表于 08-17 10:07 ?3117次閱讀
    揭秘!基于RT-Thread探究“優(yōu)先級(jí)反轉(zhuǎn)”下的<b class='flag-5'>任務(wù)</b><b class='flag-5'>調(diào)度</b>究竟是什么樣的?| 技術(shù)集結(jié)

    單核CPU網(wǎng)關(guān)和雙核CPU網(wǎng)關(guān)有什么區(qū)別

    單核CPU網(wǎng)關(guān)與雙核CPU網(wǎng)關(guān)的核心區(qū)別在于處理能力、多任務(wù)效率、性能表現(xiàn)及適用場(chǎng)景,雙核CPU網(wǎng)關(guān)在多任務(wù)處理、復(fù)雜計(jì)算和響應(yīng)速度上具有顯
    的頭像 發(fā)表于 07-05 14:37 ?938次閱讀

    CPU密集型任務(wù)開發(fā)指導(dǎo)

    CPU密集型任務(wù)是指需要占用系統(tǒng)資源處理大量計(jì)算能力的任務(wù),需要長(zhǎng)時(shí)間運(yùn)行,這段時(shí)間會(huì)阻塞線程其它事件的處理,不適宜放在主線程進(jìn)行。例如圖像處理、視頻編碼、數(shù)據(jù)分析等。 基于多線程并發(fā)機(jī)制處理
    發(fā)表于 06-19 06:05

    工控一體機(jī)多線程任務(wù)調(diào)度優(yōu)化:聚徽分享破解工業(yè)復(fù)雜流程高效協(xié)同密碼

    任務(wù)調(diào)度作為工控一體機(jī)管理和協(xié)調(diào)各項(xiàng)任務(wù)的關(guān)鍵機(jī)制,其優(yōu)化程度直接關(guān)乎工業(yè)生產(chǎn)的效率、穩(wěn)定性與精準(zhǔn)度,宛如一把關(guān)鍵鑰匙,解鎖工業(yè)復(fù)雜流程高效協(xié)同的大門。 工業(yè)復(fù)雜流程與多線程任務(wù)
    的頭像 發(fā)表于 05-28 14:06 ?584次閱讀