機(jī)電之家資源網(wǎng)
單片機(jī)首頁(yè)|單片機(jī)基礎(chǔ)|單片機(jī)應(yīng)用|單片機(jī)開(kāi)發(fā)|單片機(jī)文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開(kāi)發(fā)
培訓(xùn)信息
贊助商
使用 OProfile for Linux on POWER 識(shí)別性能瓶頸
使用 OProfile for Linux on POWER 識(shí)別性能瓶頸
 更新時(shí)間:2009-8-12 16:53:17  點(diǎn)擊數(shù):0
【字體: 字體顏色

OProfile 例子
您可以使用 OProfile 來(lái)分析處理器周期、TLB 失誤、內(nèi)存引用、分支預(yù)測(cè)失誤、緩存失誤、中斷處理程序,等等。同樣,您可以使用 opcontrol 的 --list-events 選項(xiàng)來(lái)提供完整的特定處理器上可監(jiān)視事件列表。

下面的例子演示了如何使用 OProfile for Linux on POWER。第一個(gè)例子監(jiān)視處理器周期,以發(fā)現(xiàn)編寫(xiě)不當(dāng)、會(huì)導(dǎo)致潛在性能瓶頸的算法。雖然這是一個(gè)很小的例子,但是當(dāng)您分析一個(gè)應(yīng)用程序,期望發(fā)現(xiàn)大部分處理器周期究竟用在什么地方時(shí),仍可以借鑒這里的方法。然后您可以進(jìn)一步分析這部分代碼,看是否可以對(duì)其進(jìn)行優(yōu)化。

第二個(gè)例子要更為復(fù)雜一些 —— 它演示了如何發(fā)現(xiàn)二級(jí)(level 2,L2)數(shù)據(jù)緩存失誤,并為減少數(shù)據(jù)緩存失誤的次數(shù)提供了兩套解決方案。

例 1: 分析編寫(xiě)不當(dāng)?shù)拇a
這個(gè)例子的目的是展示如何編譯和分析一個(gè)編寫(xiě)不當(dāng)?shù)拇a示例,以分析哪個(gè)函數(shù)性能不佳。這是一個(gè)很小的例子,只包含兩個(gè)函數(shù) —— slow_multiply()fast_multiply() —— 這兩個(gè)函數(shù)都是用于求兩個(gè)數(shù)的乘積,如下面的清單 1 所示。

清單 1. 兩個(gè)執(zhí)行乘法的函數(shù)

分析這個(gè)代碼,并使用 opannotate 對(duì)其進(jìn)行分析,該工具使您可以用 OProfile 注釋查看源代碼。首先必須利用調(diào)試信息來(lái)編譯源代碼,opannotate 要用它來(lái)添加注釋。使用 Gnu Compiler Collections C 編譯器,即 gcc,通過(guò)運(yùn)行以下命令來(lái)編譯清單 1 中的例子。注意,-g 標(biāo)志意味著要添加調(diào)試信息。

接下來(lái),使用 清單 2 中的命令分析該代碼,然后使用 CYCLES 事件計(jì)算處理器周期,以分析結(jié)果。

清單 2. 用來(lái)分析乘法例子的命令

最后,使用 opannotate 工具和 --source 選項(xiàng)生成源代碼,或者和 --assembly 選項(xiàng)一起生成匯編代碼。具體使用這兩個(gè)選項(xiàng)中的哪一個(gè)選項(xiàng),或者是否同時(shí)使用這兩個(gè)選項(xiàng),則取決于您想要分析的詳細(xì)程度。對(duì)于這個(gè)例子,只需使用 --source 選項(xiàng)來(lái)確定大部分處理器周期發(fā)生在什么地方即可。

清單 3. 對(duì)乘法例子的 opannotate 結(jié)果的分析

清單 3 中下面的幾行將顯示兩個(gè)乘法函數(shù)中所使用的 CYCLES 數(shù):


您可以看到,fast_mulitply() 只使用了 79 個(gè)樣本,而 slow_multiply() 使用了 6065 個(gè)樣本。雖然這是一個(gè)很小的例子,在現(xiàn)實(shí)中不大可能出現(xiàn),但它仍然足以演示如何剖析代碼,并為發(fā)現(xiàn)性能瓶頸而對(duì)其進(jìn)行分析。

例 2:發(fā)現(xiàn)二級(jí)數(shù)據(jù)緩存失誤
這個(gè)例子比第一個(gè)例子要復(fù)雜一些,它需要發(fā)現(xiàn)二級(jí)(L2)數(shù)據(jù)緩存失誤。POWER 處理器包含芯片二級(jí)緩存(on-chip L2 cache),這是鄰近處理器的一種高速存儲(chǔ)器。處理器從 L2 緩存中訪問(wèn)經(jīng)常修改的數(shù)據(jù)。當(dāng)兩個(gè)處理器共享一個(gè)數(shù)據(jù)結(jié)構(gòu),并同時(shí)修改那個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí),就有可能引發(fā)問(wèn)題。CPU1 在它的 L2 緩存中包含數(shù)據(jù)的一個(gè)副本,而 CPU2 修改了這個(gè)共享的數(shù)據(jù)結(jié)構(gòu)。CPU1 L2 緩存中的副本現(xiàn)在是無(wú)效的,必須進(jìn)行更新。CPU1 必須花費(fèi)大量步驟從主存中檢索數(shù)據(jù),這需要占用額外的處理器周期。圖 1 展示了兩個(gè)處理器,它們?cè)诟髯缘?L2 緩存中包含一個(gè)共享數(shù)據(jù)結(jié)構(gòu)的一個(gè)副本。

圖 1. 共享一個(gè)數(shù)據(jù)結(jié)構(gòu)的兩個(gè)處理器

在這個(gè)例子中,您將查看這個(gè)數(shù)據(jù)結(jié)構(gòu)(如清單 4 所示),并分析兩個(gè)處理器同時(shí)修改這個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí)出現(xiàn)的情景)。然后觀察數(shù)據(jù)緩存失誤,并考察用來(lái)修正這個(gè)問(wèn)題的兩種解決方案。

清單 4. 共享的數(shù)據(jù)結(jié)構(gòu)

清單 5 中的程序使用 clone() 系統(tǒng)調(diào)用和 VM_CLONE 標(biāo)志生成一個(gè)子進(jìn)程。VM_CLONE 標(biāo)志會(huì)導(dǎo)致子進(jìn)程和父進(jìn)程在同一個(gè)存儲(chǔ)空間中運(yùn)行。父線程修改該數(shù)據(jù)結(jié)構(gòu)的第一個(gè)元素,而子線程則修改第二個(gè)元素。

清單 5. 演示 L2 數(shù)據(jù)緩存失誤的代碼示例

使用 gcc 編譯器,運(yùn)行清單 6 中的命令不帶優(yōu)化地編譯這個(gè)示例程序。

清單 6. 用于編譯清單 5 中例子代碼的命令

現(xiàn)在您可以用 OProfile 分析上述程序中出現(xiàn)的 L2 數(shù)據(jù)緩存失誤。

對(duì)于這個(gè)例子,作者在一臺(tái) IBM eServer™ OpenPower™ 710 上執(zhí)行和分析了這個(gè)程序,該機(jī)器有兩個(gè) POWER5 處理器,并運(yùn)行 SLES9 Service Pack 1 (SLES9SP1)。將 --list-events 標(biāo)志傳遞給 opcontrol,以判斷是哪一個(gè)事件負(fù)責(zé)監(jiān)視 L2 數(shù)據(jù)緩存失誤。對(duì)于基于 POWER5 處理器的、運(yùn)行 SLES9SP1 的系統(tǒng),由 PM_LSU_LMQ_LHR_MERGE_GP9 事件監(jiān)視 L2 數(shù)據(jù)緩存失誤。如果您將樣本計(jì)數(shù)設(shè)置為 1000,比如在這個(gè)例子中,那么 OProfile 將從每 1000 個(gè)硬件事件抽取一個(gè)樣本。如果使用不同的平臺(tái),例如基于 POWER4 處理器的服務(wù)器,那么這樣的事件也會(huì)有所不同。

使用 清單 7 中的命令分析這個(gè)例子代碼,如下所示:

清單 7. 用來(lái)分析清單 5 所示例子中的 L2 數(shù)據(jù)緩存失誤的命令

在分析來(lái)自 opreport 的結(jié)果時(shí),您可以看到,在函數(shù) main()inc_second() 中存在很多緩存失誤。opreport 的 -l 選項(xiàng)將輸出符號(hào)信息,而實(shí)質(zhì)上輸出的應(yīng)該只是二進(jìn)制映像名。同樣,緩存失誤的起因也是兩個(gè)處理器修改一個(gè)共享的數(shù)據(jù)結(jié)構(gòu),這個(gè)數(shù)據(jù)結(jié)構(gòu)大小為 8 字節(jié),放在一個(gè) 128 字節(jié)的緩存行中。

消除數(shù)據(jù)緩存失誤的一種方法是填充數(shù)據(jù)結(jié)構(gòu),使得它的每一個(gè)元素都存儲(chǔ)在各自的緩存行中。清單 8 包含一個(gè)修改后的結(jié)構(gòu),其中有 124 字節(jié)的填充物。

清單 8. 帶填充物的數(shù)據(jù)結(jié)構(gòu),每個(gè)元素放進(jìn)不同的緩存行中

圖 2 展示了在填充數(shù)據(jù)結(jié)構(gòu)后,如何使得每個(gè)處理器上的每個(gè)數(shù)據(jù)元素都存儲(chǔ)在各自的緩存行中。

圖 2. 共享填充后的數(shù)據(jù)結(jié)構(gòu)的兩個(gè)處理器

像前面那樣重新編譯該程序,但是這一次使用修改后的數(shù)據(jù)結(jié)構(gòu)。然后使用 清單 9 中的命令再次分析結(jié)果。

清單 9. 填充數(shù)據(jù)結(jié)構(gòu)后用于 profile L2 數(shù)據(jù)緩存失誤的命令

Opreport 表明,由于沒(méi)有發(fā)現(xiàn)抽樣數(shù)據(jù),所以可能存在錯(cuò)誤。然而,隨著對(duì)共享數(shù)據(jù)結(jié)構(gòu)的修改,這是可以預(yù)期的,因?yàn)槊總(gè)數(shù)據(jù)元素都在自己的緩存行中,所以不存在 L2 緩存失誤。

現(xiàn)在可以考察 L2 緩存失誤在處理器周期上的代價(jià)。首先,分析使用未填充的原有共享數(shù)據(jù)結(jié)構(gòu)的代碼(清單 4)。您將進(jìn)行抽樣的事件是 CYCLES。使用 清單 10 中的命令針對(duì) CYCLES 事件分析這個(gè)例子。

清單 10. 用于 profile 清單 5 所示例子中處理器周期數(shù)的命令

現(xiàn)在,使用 清單 11 中的命令分析使用填充后的數(shù)據(jù)結(jié)構(gòu)的例子代碼(清單 8)。

清單 11. 用于分析使用填充后的數(shù)據(jù)結(jié)構(gòu)的例子中處理器周期數(shù)的命令

不出所料,隨著 L2 緩存失誤數(shù)量的增加,處理器周期數(shù)也有所增加。其主要原因是,與從 L2 緩存取數(shù)據(jù)相比,從主存獲取數(shù)據(jù)代價(jià)昂貴。

避免兩個(gè)處理器之間緩存失誤的另一種方法是在相同處理器上運(yùn)行兩個(gè)線程。通過(guò)使用 Cpu 相似性(affinity),將一個(gè)進(jìn)程綁定到一個(gè)特定的處理器,下面的例子演示了這一點(diǎn)。在 Linux 上,sched_setaffinity() 系統(tǒng)調(diào)用在一個(gè)處理器上運(yùn)行兩個(gè)線程。 清單 12 提供了原來(lái)的示例程序的另一個(gè)變體,其中使用 sched_setaffinity() 調(diào)用來(lái)執(zhí)行這一操作。

清單 12. 利用 cpu 相似性來(lái)避免 L2 緩存失誤的示例代碼

這個(gè)例子在同處理器上運(yùn)行兩個(gè)線程,共享數(shù)據(jù)結(jié)構(gòu)存放在一個(gè)處理器上的一個(gè) L2 緩存行中。這樣應(yīng)該可以導(dǎo)致零緩存失誤。使用前面描述的步驟分析緩存失誤,以驗(yàn)證在一個(gè)處理器上運(yùn)行兩個(gè)進(jìn)程時(shí),是否不存在 L2 緩存失誤。對(duì)于數(shù)據(jù)緩存失誤這個(gè)問(wèn)題,第三種解決方法是使用編譯器優(yōu)化,這樣可以減少緩存失誤的數(shù)量。然而,在某些環(huán)境下,這不是一個(gè)合適的選擇,您仍然必須分析代碼,并對(duì)不良性能做出改正。

結(jié)束語(yǔ)
分析是開(kāi)發(fā)過(guò)程中最困難的任務(wù)之一。為了使代碼獲得最佳性能,好的工具是必不可少的。OProfile 就是這樣一種工具,目前它提供了針對(duì) Linux on POWER 的分析功能。對(duì)于其他平臺(tái)上的可以快速移植到 Linux on POWER 的 Linux,還有其他許多性能和調(diào)試工具。除了處理器事件的類型有所差別外,在基于 POWER 處理器的 Linux 平臺(tái)上運(yùn)行 OProfile 與在其他架構(gòu)上運(yùn)行 OProfile 是類似的。所以,如果在其他平臺(tái)上使用過(guò) OProfile,那么您應(yīng)該在很短時(shí)間內(nèi)就可以知道如何在 Linux on POWER 上運(yùn)行 OProfile。

致謝
我要感謝 Linda Kinnunen,是她提供了文檔模板并對(duì)本文進(jìn)行了審校,我還要感謝 Maynard Johnson 對(duì)本文進(jìn)行了技術(shù)上的審校。

 
了解關(guān)于 OProfile 的知識(shí),學(xué)習(xí)如何在基于 IBM® POWER™ 處理器、運(yùn)行 Linux™ 的服務(wù)器上使用它。首先,閱讀關(guān)于 OProfile 的概述,并了解它在 Linux on POWER 上的實(shí)現(xiàn),然后跟隨作者給出的兩個(gè)例子,學(xué)習(xí)如何在 Linux on POWER 平臺(tái)上使用 OProfile 分析代碼和結(jié)果。

簡(jiǎn)介
作為一名開(kāi)發(fā)人員,在試圖提高代碼效率時(shí),您可能發(fā)現(xiàn)性能瓶頸是您要面對(duì)的最困難的任務(wù)之一。代碼分析(code profiling)是一種可以使這項(xiàng)任務(wù)變得更容易的方法。代碼分析包括對(duì)那些表示運(yùn)行系統(tǒng)上的某些處理器活動(dòng)的數(shù)據(jù)樣本進(jìn)行分析。OProfile 為 POWER 上的 Linux 提供了這種解決方案。OProfile 被包含在最新的 IBM® 支持的 Linux for POWER 發(fā)行版本中:Red Hat Enterprise Linux 4 (RHEL4) 和 SUSE LINUX Enterprise Server 9 (SLES9)。本文將介紹 OProfile for Linux on POWER,并提供兩個(gè)例子,演示如何使用它來(lái)發(fā)現(xiàn)性能瓶頸。

代碼分析概述
OProfile for Linux on POWER 使用了一個(gè)內(nèi)核模塊和一個(gè)用戶空間守護(hù)進(jìn)程,前者可以訪問(wèn)性能計(jì)數(shù)寄存器,后者在后臺(tái)運(yùn)行,負(fù)責(zé)從這些寄存器中收集數(shù)據(jù)。在啟動(dòng)守護(hù)進(jìn)程之前, OProfile 將配置事件類型以及每種事件的樣本計(jì)數(shù)(sample count)。如果沒(méi)有配置任何事件,那么 OProfile 將使用 Linux on POWER 上的默認(rèn)事件,即 CYCLES,該事件將對(duì)處理器循環(huán)進(jìn)行計(jì)數(shù)。事件的樣本計(jì)數(shù)將決定事件每發(fā)生多少次計(jì)數(shù)器才增加一次。OProfile 被設(shè)計(jì)成可以在低開(kāi)銷下運(yùn)行,從而使后臺(tái)運(yùn)行的守護(hù)進(jìn)程不會(huì)擾亂系統(tǒng)性能。

OProfile 具有對(duì) POWER4™、POWER5™ 和 PowerPC® 970 處理器的內(nèi)核支持。PowerPC 970 和 POWER4 處理器有 8 個(gè)計(jì)數(shù)寄存器,而 POWER5 處理器有 6 個(gè)計(jì)數(shù)寄存器。在不具備 OProfile 內(nèi)核支持的架構(gòu)上使用的則是計(jì)時(shí)器(timer)模式。在這種模式下,OProfile 使用了一個(gè)計(jì)數(shù)器中斷,對(duì)于禁用中斷的代碼,OProfile 不能對(duì)其進(jìn)行分析。

OProfile 工具
與 OProfile 內(nèi)核支持一起提供的還有一些與內(nèi)核交互的用戶空間工具,以及分析收集到的數(shù)據(jù)的工具。如前所述,OProfile 守護(hù)進(jìn)程收集樣本數(shù)據(jù)。控制該守護(hù)進(jìn)程的工具稱作 opcontrol。表 1 列出了用于 opcontrol 的一些常見(jiàn)的命令行選項(xiàng)。本文的后面還將描述 opreport 和 opannotate 這兩個(gè)工具,它們都是用于分析收集到的數(shù)據(jù)的工具。在 OProfile 手冊(cè)的第 2.2 節(jié)中,可以找到對(duì)所有 OProfile 工具的概述。(請(qǐng)參閱參考資料。)

RHEL4 和 SLES9 上支持的處理器事件類型是不同的,正如不同 POWER 處理器上支持的事件類型也會(huì)有所變化一樣。您可以使用 opcontrol 工具和 --list-events 選項(xiàng)獲得自己平臺(tái)所支持的那些事件的列表。

表 1. opcontrol 命令行選項(xiàng)

opcontrol 選項(xiàng)描述
--list-events列出處理器事件和單元屏蔽(unit mask)
--vmlinux=<kernel image>將要分析的內(nèi)核鏡像文件
--no-vmlinux不分析內(nèi)核
--reset清除當(dāng)前會(huì)話中的數(shù)據(jù)
--setup在運(yùn)行守護(hù)進(jìn)程之前對(duì)其進(jìn)行設(shè)置
--event=<processor event>監(jiān)視給定的處理器事件
--start開(kāi)始取樣
--dump使數(shù)據(jù)流到守護(hù)進(jìn)程中
--stop停止數(shù)據(jù)取樣
-h關(guān)閉守護(hù)進(jìn)程
  int fast_multiply(x,  y) {        return x * y;}int slow_multiply(x, y) {        int i, j, z;        for (i = 0, z = 0; i < x; i++)                 z = z + y;        return z;}int main(){        int i,j;        int x,y;        for (i = 0; i < 200; i ++) {                for (j = 0; j " 30 ; j++) {                        x = fast_multiply(i, j);                        y = slow_multiply(i, j);                }        }        return 0;}
 gcc  -g multiply.c -o multiply   
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup --event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./multiply# opcontrol --dump# opcontrol --stopStopping profiling.# opcontrol -hStopping profiling.Killing daemon.
# opannotate --source ./multiply/*  * Command line: opannotate --source ./multiply  *  * Interpretation of command line: * Output annotated source file with samples * Output all files *  * CPU: ppc64 POWER5, speed 1656.38 MHz (estimated) * Counted CYCLES events (Processor cycles) with a unit mask of0x00 (No unit mask) count 1000 *//*  * Total samples for file : "/usr/local/src/badcode/multiply.c" *  *   6244 100.000 */               :int fast_multiply(x, y)     36  0.5766 :{ /* fast_multiply total:     79  1.2652 */    26  0.4164 :        return x * y;    17  0.2723 :}               :               :int slow_multiply(x, y)     50  0.8008 :{ /* slow_multiply total:   6065 97.1332 */               :        int i, j, z;  2305 36.9154 :        for (i = 0, z = 0; i " x; i++)   3684 59.0006 :                z = z + y;    11  0.1762 :        return z;    15  0.2402 :}               :               :int main()               :{ /* main total:    100  1.6015 */               :        int i,j;               :        int x,y;               :     1  0.0160 :        for (i = 0; i " 200; i ++) {     6  0.0961 :                for (j = 0; j " 30 ; j++) {    75  1.2012 :                        x = fast_multiply(i, j);    18  0.2883 :                        y = slow_multiply(i, j);               :                }               :        }               :        return 0;               :}               
36  0.5766 :{ /* fast_multiply total:     79  1.2652 */
50  0.8008 :{ /* slow_multiply total:   6065 97.1332 */
struct shared_data_struct {   unsigned int data1;   unsigned int data1;}
#include <stdlib.h>#include <sched.h>struct shared_data_struct {        unsigned int data1;        unsigned int data2;};struct shared_data_struct shared_data;static int inc_second(struct shared_data_struct *);int main(){        int i, j, pid;        void *child_stack;        /* allocate memory for other process to execute in */        if((child_stack = (void *) malloc(4096)) == NULL) {                perror("Cannot allocate stack for child");                exit(1);        }        /* clone process and run in the same memory space */        if ((pid = clone((void *)&inc_second, child_stack,
CLONE_VM, &shared_data)) < 0) { perror("clone called failed."); exit(1); } /* increment first member of shared struct */ for (j = 0; j < 2000; j++) { for (i = 0; i < 100000; i++) { shared_data.data1++; } } return 0;}int inc_second(struct shared_data_struct *sd){ int i,j; /* increment second member of shared struct */ for (j = 1; j < 2000; j++) { for (i = 1; i < 100000; i++) { sd->data2++; } }}
gcc -o cache-miss cache-miss.c
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=PM_LSU_LMQ_LHR_MERGE_GP9:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted PM_LSU_LMQ_LHR_MERGE_GP9 events (Dcache miss occurred for
the same real cache line as earlier req, merged into LMQ) with a
unit mask of 0x00 (No unit mask) count 1000samples % symbol name47897 58.7470 main33634 41.2530 inc_second
struct shared_data_struct {   unsigned int data1;   char pad[124];   unsigned int data1;
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=PM_LSU_LMQ_LHR_MERGE_GP9:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss error: no sample files found: profile specification too strict ?
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted CYCLES events (Processor cycles) with a unit mask of 0x00
(No unit mask) count 1000samples % symbol name121166 53.3853 inc_second105799 46.6147 main
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted CYCLES events (Processor cycles) with a unit mask of 0x00
(No unit mask) count 1000samples % symbol name104916 58.3872 inc_second74774 41.6128 main
#include <stdlib.h>#include <sched.h>struct shared_data_struct {        unsigned int data1;        unsigned int data2;};struct shared_data_struct shared_data;static int inc_second(struct shared_data_struct *);int main(){        int i, j, pid;        cpu_set_t cmask;        unsigned long len = sizeof(cmask);        pid_t p = 0;        void *child_stack;        __CPU_ZERO(&cmask);        __CPU_SET(0, &cmask);        /* allocate memory for other process to execute in */        if((child_stack = (void *) malloc(4096)) == NULL) {                perror("Cannot allocate stack for child");                exit(1);        }        /* clone process and run in the same memory space */        if ((pid = clone((void *)&inc_second, child_stack,
CLONE_VM, &shared_data)) < 0) { perror("clone called failed"); exit(1); } if (!sched_setaffinity(0, len, &cmask)) { printf("Could not set cpu affinity for current
process.\n"); exit(1); } if (!sched_setaffinity(pid, len, &cmask)) { printf("Could not set cpu affinity for cloned
process.\n"); exit(1); } /* increment first member of shared struct */ for (j = 0; j < 2000; j++) { for (i = 0; i < 100000; i++) { shared_data.data1++; } } return 0;}int inc_second(struct shared_data_struct *sd){ int i,j; /* increment second member of shared struct */ for (j = 1; j < 2000; j++) { for (i = 1; i < 100000; i++) { sd->data2++; } }}
  • 上一篇: Linux內(nèi)核級(jí)后門(mén)的原理及簡(jiǎn)單實(shí)戰(zhàn)
  • 下一篇: Linux 2.6內(nèi)核中新的鎖機(jī)制--RCU
  • 發(fā)表評(píng)論   告訴好友   打印此文  收藏此頁(yè)  關(guān)閉窗口  返回頂部
    熱點(diǎn)文章
     
    推薦文章
     
    相關(guān)文章
    網(wǎng)友評(píng)論:(只顯示最新5條。)
    關(guān)于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機(jī)電之家 | 會(huì)員助手 | 免費(fèi)鏈接

    點(diǎn)擊這里給我發(fā)消息66821730(技術(shù)支持)點(diǎn)擊這里給我發(fā)消息66821730(廣告投放) 點(diǎn)擊這里給我發(fā)消息41031197(編輯) 點(diǎn)擊這里給我發(fā)消息58733127(審核)
    本站提供的機(jī)電設(shè)備,機(jī)電供求等信息由機(jī)電企業(yè)自行提供,該企業(yè)負(fù)責(zé)信息內(nèi)容的真實(shí)性、準(zhǔn)確性和合法性。
    機(jī)電之家對(duì)此不承擔(dān)任何保證責(zé)任,有侵犯您利益的地方請(qǐng)聯(lián)系機(jī)電之家,機(jī)電之家將及時(shí)作出處理。
    Copyright 2007 機(jī)電之家 Inc All Rights Reserved.機(jī)電之家-由機(jī)電一體化網(wǎng)更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術(shù)支持

    主辦:杭州市高新區(qū)(濱江)機(jī)電一體化學(xué)會(huì)
    中國(guó)行業(yè)電子商務(wù)100強(qiáng)網(wǎng)站

    網(wǎng)站經(jīng)營(yíng)許可證:浙B2-20080178-1