杜秀芳
【摘要】本文主要介紹了在多核系統中從軟件上開發的一種CPU優化技術。這種優化技術針對CPU使用不均衡的問題,利用任務調度算法能自動平衡CPU的使用,提高多核系統中CPU的使用率,從而發揮CPU的性能優勢。
【關鍵詞】多核系統 CPU優化 任務調度
0 引言
隨著CPU技術的發展,CPU性能的提高方向已經從單核CPU頻率的提高往CPU核數的提高轉變。以INTEL至強系列為例,Xeon D-1521是四核CPU,每核的主頻是2.4GHz;Xeon D-1531處理器是6核設備,主頻是2.2GHz,Xeon E5 v4處理器是10核心設備,主頻是2.2GHzo這三款處理器都是采用14nm工藝制造,主頻并沒有太大分別,在跑分上分別為6980、9730、13923。但是,CPU技術提高了,應用技術并沒有很好的配合提高,并不能發揮CPU的性能優勢。本文開發了一種CPU優化技術,可以提高多核系統中CPU的使用率。
1 CPU使用的不均衡問題
在CPU技術的發展過程中,核心數量的增長是近年的趨勢,對于多核支撐,需要程序開發人員自行分配核心的工作量。但這件事并不是一個簡單的工作,所謂“一核有難十核圍觀”。雖然后來的技術有一定的改善,但是還是沒有實現均衡的使用。
2 綁核的任務系統
本文開發了一套任務調度框架,在本程序框架下運行的程序,會自動平衡多核CPU的使用,達到較優的多核使用效率。本框架是在linux環境下開發和調試的,代碼使用C語言。
2.1 action的定義
本框架把每一個要完成的任務定義為一個action。一個action,從業務上是一個軟件要處理的事務單元,也可以多個事務單元完成一個事務;從代碼上任務可以理解為函數。以路由器為例,從業務上,它處理的任務都是I/O相關的內容,所以每個任務包含I/O相關的信息,比如I/O請求等等;從代碼上,用一個函數指針來描述任務。由于我們這個任務調度算法設計的初衷是方便任務調度、提高CPU使用的效率。所以要求任務的處理時間不能太長。這個太長在CPU領域里面定位為100ms,這個是個估計值。任務的處理時間短是任務的內在要求。
當任務的時間過長,會損耗框架的靈活調度。所以當一個任務的處理時間可能比較長的時候,需要拆分成多個任務,這就是任務拆分。任務拆分的目的是控制單個任務的處理時間。
2.2 線程和CPU的關系
對于高性能處理器,往往有多個CPU,為了講清楚這個關系,我們假設CPU的核數是6核。
在操作系統層面上,基本的運行單元是進程,進程中的調度單元是線程。一個進程可以有多個線程,但是至少要有一個線程,否則就沒必要存在。對于進程所擁有的資源,線程也是可以共享的。在有了線程的操作系統中,進程是分配資源的基本單元,而線程是獨立運行和獨立調度的基本單元。相比較進程來講,線程更小,而且不擁有系統資源,所以對線程的調度開銷會小得多,通過調度線程可以提高系統的多個程序并發執行的程度。
在配置過程中,一個CPU可以綁定多個線程,即多個線程公用一個CPU。每個線程綁定一個CPU時,系統的性能較高。所以在主程序啟動之初,需要把每個線程跟CPU分別綁定。
2.3 CPU的線程的動卜態補償
為了適應程序開發的多樣性,這里任務也分為兩種:一種任務是獨立的,即這種任務可以獨立的運行在一個線程上,不依賴其他的任務,可以獨立完成;另一種任務是非獨立的,即任務之間有相關性,根據這個要求,這類任務需要運行在同樣的線程上,以避免共享資源的訪問導致性能下降。獨立的任務跟所在的線程無關,可以運行在任何的線程上;非獨立的任務只能運行在同一個線程上。通常來說,對于大多數程序開發,獨立的任務占大多數。
對于非獨立的任務,任務的分配機制是固定的,由使用者自行指定線程(也就是固定線程)。
對于獨立的任務,根據線程(CPU)的忙碌程度,把任務分配到不太忙碌的線程,實現CPU的均衡配置,這就是任務遷移。
2.4 技術關鍵點
實現上,首先要設置進程的CPU數量,也就是該程序所在進程使用多少個CPU。這里采用的接口是CPU親和度接口族,主要是這幾個接口。
#define_GNU_SOURCE/關See feature_test_macros(7)*/
int sched_setaffinity(pid_t pid,size_t epusetsize,cpu_set_t*mask);
int sched_getaffinity(pid_t pid,size_t cpusetsize,cpu_set_t*mask);
其中,pid是要CPU的進程pid;mask是二進制掩碼,比如0x000F表示使用CPUO、CPU1、CPU2、CPU3;0x00F1表示使用CPU0、CPU4、CPU5、CPU6、CPU7。
第二個技術點是要設置線程的CPU關系,這一點在實現上需要使用線程CPU綁定函數,這里面
int pthread_setaffinity_np(pthread_t thread,size_t epusetsize,const cpu_set_t*cpuset);
int pthread-getaffinity-np(pthread_t thread,size_t cpusetsize,cpu_set_t*cpuset);
其中,thread為線程id; cpusetsize為cpu數組大小,固定填sizeof(cpu_set_t);cpuset是一個集合,角來表示設置哪些CPU跟這個線程綁定。
這個集合需要提前創建,使用CPU_SEI,接口實現添加。例如:
CPU ZERO(&cpuset;);
for(j=0;i<8;j++)
CPU_SET(j,&cpuset;);
這一段代碼的意思是設置一個CPU包含CPU0-CPU7的集合。
另一個關鍵點就是要求編程人員能夠對任務進行劃分,劃分成盡量與線程無關的任務塊,這樣才能實現任務的自由切換。
3 結束語
CPU技術的發展日新月異,CPU軟件技術的發展也是在逐步提高,逐步發揮出硬件的優勢,本文提供了一種在多核設備上從軟件上優化CPU的技術方案。希望能帶給大家一點思路。
參考文獻:
[1]郭建偉.靈活調度,激活多核CPU“潛力”[J].電腦知識與技術(經驗技巧),2017(11):33-34.