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

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

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

了解CPI對分析程序性能的意義

Linux閱碼場 ? 來源:cg ? 2018-12-15 10:30 ? 次閱讀

阿里云系統(tǒng)團(tuán)隊,是由原淘寶內(nèi)核組擴(kuò)建而成,2013年淘寶內(nèi)核組響應(yīng)阿里巴巴集團(tuán)的號召,整建制轉(zhuǎn)入阿里云,開始為云計算底層系統(tǒng)構(gòu)建完善的系統(tǒng)支持。 阿里云系統(tǒng)團(tuán)隊是由一群具有高度使命感和自我追求的內(nèi)核開發(fā)人員組成,團(tuán)隊中的大多數(shù)人,都是活躍的社區(qū)內(nèi)核開發(fā)人員。目前的工作領(lǐng)域主要涉及(但不限于) Linux內(nèi)核的內(nèi)存管理、文件系統(tǒng)、網(wǎng)絡(luò)和內(nèi)核維護(hù)構(gòu)建,以及和內(nèi)核相關(guān)聯(lián)的用戶態(tài)庫和工具。如果你對我們的工作很感興趣,歡迎加入我們,請將簡歷發(fā)送至 tao.ma at linux.alibaba.com或者boyu.mt at alibaba-inc.com。

1. 什么是 CPI ?

本小節(jié)講述為什么使用 CPI 分析程序性能的意義。如果已經(jīng)非常了解 CPI 對分析程序性能的意義,可以跳過本小節(jié)的閱讀。

1.1 程序怎么樣才能跑得快 ?

理解什么是 CPI,首先讓我們思考一個問題:在一個給定的處理器上,如何才能讓程序跑得更快呢?

假設(shè)程序跑得快慢的標(biāo)準(zhǔn)是程序的執(zhí)行時間,那么程序執(zhí)行的快慢,就可以用如下公式來表示:

因此,要想程序跑得快,即減少程序執(zhí)行時間,我們就需要在以下三個方面下功夫:

減少程序總指令數(shù)

要減少程序執(zhí)行的總指令數(shù),可能有以下手段:

算法優(yōu)化;好的算法設(shè)計,可能帶來更少的指令執(zhí)行數(shù)。

更高效的編譯器或者解釋器;新的編譯器或者解釋器,可能對同樣的源代碼,生成更少的機(jī)器碼。

用更底層的語言優(yōu)化;這是為何 Linux 內(nèi)核代碼使用 C 語言,并且還喜歡內(nèi)聯(lián)匯編。

更新的處理器指令;新的處理器指令,對處理某類特殊目的運算更有幫助,而新版本編譯器最重要的工作就是,在新的處理器上,用最新的高效指令;例如,x86 SSE,AVX 指令。

減少每 CPU 時鐘周期時間

這一點很容易理解,縮短 CPU 時鐘周期的時間,實際上就是要提高 CPU 的主頻。這正是 Intel 過去戰(zhàn)無不勝的法寶之一。今天,由于主頻的提高已經(jīng)到了制造工藝的極限,CPU 時鐘周期的時間很難再繼續(xù)降低了。

減少每指令執(zhí)行所需平均時鐘周期數(shù)

如何減少每指令執(zhí)行所需平均 CPU 時鐘周期數(shù)呢?讓我們先從 CPU 設(shè)計角度看一下:

標(biāo)量處理器 (Scalar Processor) ;一個 CPU 時鐘周期只能執(zhí)行一條指令;

超標(biāo)量處理器 (Superscalar Processor);一個 CPU 時鐘周期可以執(zhí)行多條指令。

因此不難看出,如果使用支持超標(biāo)量處理器的 CPU,利用 CPU 流水線提高指令并行度,那么就可以達(dá)到我們的目的了。流水線的并行度越高,執(zhí)行效率越高,那么每指令執(zhí)行所需平均時鐘周期數(shù)就會越低。

當(dāng)然,流水線的并行度和效率,又取決于很多因素,例如,取指令速度,訪存速度,指令亂序執(zhí)行 (Out-Of-Order Execution),分支預(yù)測執(zhí)行 (Branch Prediction Execution),投機(jī)執(zhí)行 (Speculative Execution)的能力。一旦流水線并行執(zhí)行的能力降低,那么程序的性能就會受到影響。關(guān)于超標(biāo)量處理器,流水線,亂序執(zhí)行,投機(jī)執(zhí)行的細(xì)節(jié),這里不再一一贅述,請查閱相關(guān)資料。

另外,在 SMP,或者多核處理器系統(tǒng)里,程序還可以通過并行編程來提高指令的并行度,因此,這也是為什么今天在 CPU 主頻再難以提高的情況下,CPU 架構(gòu)轉(zhuǎn)為 Multi-Core 和 Many-Core。

由于提高 CPU 主頻的同時,又要保障一個 CPU 時鐘周期可以執(zhí)行更多的指令,因此處理器廠商需要不斷地提高制造工藝,降低 CPU 的芯片面積和功耗。

1.2 CPI 和 IPC

在計算機(jī)體系結(jié)構(gòu)領(lǐng)域,經(jīng)??梢钥吹?CPI 的使用。CPI 即 Cycle Per Instruction 的縮寫,它的含義就是每指令周期數(shù)。此外,在一些場合,也可以經(jīng)??吹?IPC,即 Instruction Per Cycle,含義為每周期指令數(shù)。

因此不難得出,CPI 和 IPC 的關(guān)系為,

使用 CPI 這個定義,本文開篇用于衡量程序執(zhí)行性能的公式,如果具體到單 CPU 的程序執(zhí)行性能場景,實際上可以表示為:

由于受到硅材料和制造工藝的限制,處理器主頻的提高已經(jīng)面臨瓶頸,因此,程序性能的提高,主要的變量在 Instruction Count 和 CPI 這兩個方面。

在 Linux 上,通過perf工具,通過 Intel 處理器提供的寄存器 (PMU),可以很容易測量一個程序的 IPC。例如,下例就可以給出 Java 程序的 IPC,8 秒多的時間里,這個 Java 程序的 IPC 是 0.54:

那么,通過 IPC,我們也可以換算出 CPI 是1/0.54,約為 1.85.

通常情況下,通過 CPI 的取值,我們可以大致判斷一個計算密集型任務(wù),到底是 CPU 密集型的還是 Memory 密集型的:

CPI 小于 1,程序通常是 CPU 密集型的;

CPI 大于 1,程序通常是 Memory 密集型的;

1.3 重新認(rèn)識 CPU 利用率

程序員來說,判斷一個計算密集型任務(wù)運行效率的重要依據(jù)就是看程序運行時的 CPU 利用率。很多人認(rèn)為 CPU 利用率高就是程序的代碼在瘋狂運行。實際上,CPU 利用率高,也有可能是 CPU 正在忙等一些資源,如訪問內(nèi)存遇到了瓶頸。

一些計算密集型任務(wù),在正常情況下,CPI 很低,性能原本很好。CPU 利用率很高。但是隨著系統(tǒng)負(fù)載的增加,其它任務(wù)對系統(tǒng)資源的爭搶,導(dǎo)致這些計算任務(wù)的 CPI 大幅上升,性能下降。而此時,很可能 CPU 利用率上看,還是很高的,但是這種 CPU 利用率的高,實際上體現(xiàn)的是 CPU 的忙等,及流水線的停頓帶來的效應(yīng)。

Brendan Gregg 曾在CPU Utilization is Wrong這篇博客中指出,CPU 利用率指標(biāo)需要結(jié)合 CPI/IPC 指標(biāo)一起來分析。并詳細(xì)介紹了前因后果。感興趣的讀者可以自行閱讀原文,或者訂閱內(nèi)核月談公眾號,閱讀我們公眾號非??孔V的譯文。

至此,相信讀者已經(jīng)清楚,在不修改二進(jìn)制程序的前提下,通過 CPI 指標(biāo)了解程序的運行性能,有著非常重要的意義。對于計算密集型的程序,只通過 CPU 利用率這樣的傳統(tǒng)指標(biāo),也無法幫助你確認(rèn)你的程序的運行效率,必須將 CPU 利用率和 CPI/IPC 結(jié)合起來看,確定程序的執(zhí)行效率。

1.4 如何分析 CPI/IPC 指標(biāo)異常?

雖然利用perf可以很方便獲取 CPI/IPC 指標(biāo),但是想分析和優(yōu)化程序高 CPI 的問題,就需要一些工具和分析方法,將 CPI 高的原因,以及與之關(guān)聯(lián)的軟件的調(diào)用棧找到,從而決定優(yōu)化方向。

關(guān)于 CPI 高的原因分析,在 Intel 64 and IA-32 Architectures Optimization Reference Manual, 附錄 B 里有介紹。其中主要的思路就是按照自頂向下的方法,自頂向下排查, 4 種引起 CPI 變高的主要原因,由于本文主要是介紹 CPI 火焰圖,

對于本小節(jié)的自頂向下的分析方法,限于篇幅所限,就不詳細(xì)展開了,我們稍后會有專門的文章做詳細(xì)介紹。

2. CPI 火焰圖

Brendan Gregg 在CPI Flame Graphs: Catching Your CPUs Napping一文中,介紹了使用 CPI 火焰圖來建立 CPI 和軟件調(diào)用棧的關(guān)聯(lián)。

我們已經(jīng)知道,光看 CPU 利用率并不能知道 CPU 在干嘛。因為 CPU 可能執(zhí)行到一條指令就停下來,等待資源了。這種等待對軟件是透明的,因此從用戶角度看,CPU 還是在被使用狀態(tài),但是實際上,指令并沒有有效地執(zhí)行,CPU 在忙等,這種 CPU 利用率并不是有效的利用率。

要發(fā)現(xiàn) CPU 在 busy 的時候?qū)嶋H上在干什么,最簡單的方法就是測量平均 CPI。CPI 高說明運行每條指令用了更多的周期。這些多出來的周期里面,通常是由于流水線的停頓周期 (Stalled Cycles) 造成的,例如,等待內(nèi)存讀寫。

而 CPI 火焰圖,可以基于 CPU 火焰圖,提供一個可視化的基于 CPU 利用率和 CPI 指標(biāo),綜合分析程序 CPU 執(zhí)行效率的方案。

下面這個 CPI 火焰圖引用自 Brendan Gregg 博客文章。

可以看到,CPI 火焰圖是基于 CPU 火焰圖,根據(jù) CPI 的大小,在每個條加上了顏色。紅色代表指令,藍(lán)色代表流水線的停頓:火焰圖中,每個函數(shù)幀的寬度,顯示了函數(shù)或其子函數(shù)在 CPU 上的次數(shù),和普通 CPU 火焰圖完全一樣。而顏色則顯示了函數(shù)在 CPU 上是運行 (running 紅色) 還是停頓 (stalled 藍(lán)色)。

火焰圖里,顏色范圍,從最高CPI為藍(lán)色(執(zhí)行最慢的指令),到最低CPI為紅色 (執(zhí)行最快的指令)?;鹧鎴D是 SVG 格式,矢量圖,因此支持鼠標(biāo)點擊縮放。

然而,Brendan Gregg 博客中的這篇博客,CPI 火焰圖是基于 FreeBSD 操作系統(tǒng)特有的命令生成的,而在 Linux 上,應(yīng)該怎么辦呢?

3. 一個小程序

讓我們寫一個人造的小程序,展示在 Linux 下 CPI 火焰圖的使用。

這是一個最簡的小程序,其中包含如下兩個函數(shù):

cpu_bound函數(shù)主體是 nop 指令的循環(huán);由于 nop 指令是不訪問內(nèi)存的最簡指令之一,因此該函數(shù) CPI 一定小于 1,屬于典型的 CPU 密集型的代碼。

memory_bound函數(shù)使用_mm_clflush驅(qū)逐緩存,人為觸發(fā)程序的 L1 D-Cache Load Miss。因此該函數(shù) CPI 必然大于 1,屬于典型的 Memory 密集型的代碼。

下面是程序的源碼:

在上述小程序運行時,我們使用如下命令生成 CPI 火焰圖,

最后生成的火焰圖如下,

可以看到,CPI 火焰圖看到的結(jié)果,是符合我們的預(yù)期的:

該程序所有的 CPU 時間,都分布在cpu_bound和memory_bound兩個函數(shù)里

同是 CPU 占用時間,但cpu_bound是紅色的,代表這個函數(shù)的指令在 CPU 上一直持續(xù)運行

而memory_bound是藍(lán)色的,代表這個函數(shù)發(fā)生了嚴(yán)重的訪問內(nèi)存的延遲,導(dǎo)致了流水線停頓,屬于忙等

4. 一個benchmark

現(xiàn)在,我們可以使用 CPI 火焰圖來分析一個略真實一些的測試場景。下面的 CPI 火焰圖,來自fio的測試場景。

這個fio對 SATA 磁盤,做多進(jìn)程同步 Direct IO 順序?qū)?,可以看到?/p>

紅顏色為標(biāo)記為 CPU Bound 的函數(shù)。其中顏色最深的是_raw_spin_lock,這是自旋鎖的等待循環(huán)引起的。

藍(lán)顏色為標(biāo)記為 Memory Bound 的函數(shù)。其中顏色最深的是fio測試程序的函數(shù)get_io_u,如果使用perf程序進(jìn)一步分析,這個函數(shù)里發(fā)生了嚴(yán)重的 LLC Cache Miss。

因為 CPI 火焰圖是矢量圖,支持縮放,所以以上結(jié)論可以通過放大get_io_u的調(diào)用棧進(jìn)一步確認(rèn),

到這里,讀者會發(fā)現(xiàn),使用 CPI 火焰圖,可以很方便地做 CPU 利用率的分析,找到和定位引發(fā) CPU 停頓的函數(shù)。一旦找到相關(guān)的函數(shù),就可以通過perf annotate命令對引起停頓的指令作出進(jìn)一步確認(rèn)。并且,我們可以利用1.4小節(jié)的自頂向下分析方法,對 CPU 哪個環(huán)節(jié)產(chǎn)生瓶頸作出判斷。最后,結(jié)合這些信息,決定優(yōu)化方向。

5. 小結(jié)

本文介紹了使用 CPI 火焰圖分析程序性能的方法。CPI 火焰圖不但展示了程序的 Call Stack 與 CPU 占用率的關(guān)聯(lián)性,而且還揭示了這些 CPU 占用率里,哪些部分是真正的有效的運行時間,哪些部分實際上是 CPU 因某些停頓造成的忙等。

系統(tǒng)管理員可以通過此工具發(fā)現(xiàn)系統(tǒng)存在的資源瓶頸,并且通過一些系統(tǒng)管理命令來緩解資源的瓶頸;例如,應(yīng)用間的 Cache 顛簸干擾,可以通過將應(yīng)用綁到不同的 CPU 上解決。

而應(yīng)用開發(fā)者則可以通過優(yōu)化相關(guān)函數(shù),來提高程序的性能。例如,通過優(yōu)化代碼減少 Cache Miss,從而降低應(yīng)用的 CPI 來減少處理器因訪存停頓造成的性能問題。

"Linux閱碼場"是專業(yè)的Linux及系統(tǒng)軟件技術(shù)交流社區(qū),企業(yè)和Linux人才的連接樞紐。

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

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208460
  • 程序
    +關(guān)注

    關(guān)注

    115

    文章

    3743

    瀏覽量

    80661

原文標(biāo)題:用CPI火焰圖分析Linux性能問題

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Arm高性能計算工具試用分析

    全球排名前20的超級計算機(jī)用戶中有70%使用Arm工具來快速理解應(yīng)用程序性能,并通過調(diào)試、分析和優(yōu)化更快地獲得結(jié)果努力。
    發(fā)表于 08-02 09:51

    什么是性能分析

    什么是性能分析 不合標(biāo)準(zhǔn)的應(yīng)用程序性能會產(chǎn)生軟件或網(wǎng)絡(luò)問題。為確保軟件滿足或超過設(shè)計的期望值,有必要分析應(yīng)用程序
    發(fā)表于 05-24 23:30 ?1622次閱讀

    快速識別應(yīng)用程序性能瓶頸

    RATIONAL QUANTIFY FOR WINDOWS能查明應(yīng)用程序性能瓶頸,從而確保使用JAVA、VISUAL C/C++和VISUAL BASIC開發(fā)的應(yīng)用程序的質(zhì)量和性能
    發(fā)表于 04-18 22:15 ?20次下載

    DVFS對程序性能影響模型

    (dynamic voltage frequency scaling,簡稱DVFS)來提升單節(jié)點的能耗表現(xiàn).但是,DVFS這一類機(jī)制同時影響到應(yīng)用的能源消耗和性能,而這一問題尚未被深入探索.專注于 DVFS 機(jī)制對應(yīng)用程序性能的影響,提出了一個
    發(fā)表于 12-30 14:56 ?1次下載

    7個好習(xí)慣快速提升Python程序性能

    使用局部變量替換模塊名字空間中的變量,例如 ls = os.linesep。一方面可以提高程序性能,局部變量查找速度更快;另一方面可用簡短標(biāo)識符替代冗長的模塊變量,提高可讀性。
    發(fā)表于 07-07 10:05 ?942次閱讀
    7個好習(xí)慣快速提升Python<b class='flag-5'>程序性能</b>

    了解 LabVIEW 程序運行性能的關(guān)鍵因素

    您相信嗎,通過幾個簡單的小技巧,您就可以成功提升超過5倍的程序運算性能?LabVIEW還提供了專業(yè)的性能分析工具幫助您能夠“看得到”您的程序性能
    的頭像 發(fā)表于 06-14 00:19 ?3764次閱讀
    <b class='flag-5'>了解</b> LabVIEW <b class='flag-5'>程序</b>運行<b class='flag-5'>性能</b>的關(guān)鍵因素

    利用矢量硬件如何提高應(yīng)用程序性能

    本次會議演示了識別和修改代碼以利用矢量硬件的過程如何提高應(yīng)用程序性能
    的頭像 發(fā)表于 05-31 11:46 ?1247次閱讀

    針對ADAS應(yīng)用優(yōu)化編譯程序性能分析

    ADAS應(yīng)用很大程度上可以使用建模解決方案并以獨立于硬件的方式實現(xiàn)。底層的編譯程序和函式庫支持將基于模型的通用實現(xiàn)移植到有很大差異的硬件平臺上,并且開銷很小,效率很高。由此導(dǎo)致的少量效率不高可以透過性能分析(profiling)
    的頭像 發(fā)表于 08-21 09:59 ?1337次閱讀

    LabVIEW開發(fā)教程之運行性能的提升技巧詳細(xì)說明

    了解如何識別和解決LabVIEW應(yīng)用程序中的性能瓶頸。使用內(nèi)置工具和VI分析器,您可以監(jiān)視VIs的內(nèi)存使用情況和執(zhí)行時間,以確定導(dǎo)致應(yīng)用程序性能
    發(fā)表于 12-05 15:28 ?10次下載
    LabVIEW開發(fā)教程之運行<b class='flag-5'>性能</b>的提升技巧詳細(xì)說明

    如何使用perf和vtune進(jìn)行性能分析

    應(yīng)用程序的開發(fā)測試過程中,對程序性能進(jìn)行分析和優(yōu)化是不可或缺的一部分。
    的頭像 發(fā)表于 12-27 09:27 ?8289次閱讀

    LabVIEW應(yīng)用程序性能瓶頸的解決

    了解如何識別和解決LabVIEW應(yīng)用程序中的性能瓶頸。使用內(nèi)置工具和VI分析器,您可以監(jiān)視VIs的內(nèi)存使用情況和執(zhí)行時間,以確定導(dǎo)致應(yīng)用程序性能
    發(fā)表于 03-29 14:03 ?8次下載
    LabVIEW應(yīng)用<b class='flag-5'>程序</b>中<b class='flag-5'>性能</b>瓶頸的解決

    通過32Gb/S光纖通道提高應(yīng)用程序性能

    電子發(fā)燒友網(wǎng)站提供《通過32Gb/S光纖通道提高應(yīng)用程序性能.pdf》資料免費下載
    發(fā)表于 07-29 09:56 ?0次下載
    通過32Gb/S光纖通道提高應(yīng)用<b class='flag-5'>程序性能</b>

    第6代光纖通道:加速全閃存數(shù)據(jù)中心的數(shù)據(jù)訪問和應(yīng)用程序性能

    電子發(fā)燒友網(wǎng)站提供《第6代光纖通道:加速全閃存數(shù)據(jù)中心的數(shù)據(jù)訪問和應(yīng)用程序性能.pdf》資料免費下載
    發(fā)表于 08-29 11:52 ?0次下載
    第6代光纖通道:加速全閃存數(shù)據(jù)中心的數(shù)據(jù)訪問和應(yīng)用<b class='flag-5'>程序性能</b>

    使用Brocade Gen 7 SAN確保應(yīng)用程序性能和可靠性

    電子發(fā)燒友網(wǎng)站提供《使用Brocade Gen 7 SAN確保應(yīng)用程序性能和可靠性.pdf》資料免費下載
    發(fā)表于 09-01 10:51 ?0次下載
    使用Brocade Gen 7 SAN確保應(yīng)用<b class='flag-5'>程序性能</b>和可靠性

    PGO到底是什么?PGO如何提高應(yīng)用程序性能呢?

    PGO到底是什么?PGO如何提高應(yīng)用程序性能呢? PGO,全稱為Profile Guided Optimization,譯為“基于特征優(yōu)化”的技術(shù),是一種通過利用應(yīng)用程序的運行特征數(shù)據(jù)來優(yōu)化性能
    的頭像 發(fā)表于 10-26 17:37 ?1929次閱讀