1.1 ?多核處理器定義
多內核處理器架構是指:芯片設計工程師在單個處理器中集成兩個或多個 “執行內核(即計算引擎)”。多內核處理器可直接插入到單一處理器基座中。但是,操作系統會把它的每個執行內核作為獨立的邏輯處理器,為其分配相應的執行資源。要利用多核處理器的運算能力,需要改寫操作系統和編譯器,廣泛使用的vista, vin7 等都能支持多核體系架構。
1.2 ?多核發展趨勢
首先思考一個問題: 為什么微處理器要從單核轉向多核?
答案是: 功耗問題限制了單核不斷提高性能的發展途徑.
有幾個簡單的公式可以說明這個問題:
1)??? 處理器性能 = 主頻 * IPC , 主頻是指每秒時鐘周期數,比如1Ghz,是每秒10億個時鐘周期。IPC 是每個時鐘周期可以執行的指令數。
2)??? 處理器功耗 正比 電流*電壓^2*主頻, 而主頻正比電壓,所以
處理器功耗 正比 主頻^3 ,通過主頻提升性能,要面臨功耗以3次方的指數增長問題。所以主頻發展到一定程度后,自然轉到重點依靠提高ipc來提升性能,提升IPC可以通過提高指令的并行度實現,提高并行度,一是提高微處理器微架構的并行度,二是采用多核架構,(參考 : http://blogs.intel.com/china/2007/06/03/post_5/)前者已經發展了很多年,提升空間和投入產出比明顯不如后者,所有多核處理器是未來的方向。
?下面兩張圖看出家庭版PC和手機核心數目也很快突破10個。目前最新的mac pro 已經配備12個核心
圖1 :?目前最新的mac pro 已經配備12個核心
圖2?三星也推出了8核手機處理器
雖然商用多核(multicore)和眾核(many-core)系統越來越普遍,成本也越來越低,游戲設備、手機等移動設備也具備越來越多的核心,并發和并行越來越成為必要的技術手段,但多核程序的發展依然沒有跟上硬件的發展,很多游戲引擎和網絡引擎都還是單線程的。原因就是第一章提到的多核編程的難度。
1.3?一個多核處理器架構例子
這是基于共享緩存的多核體系架構的一個例子,一共有10個核心,不需要深入了解,這張圖唯一的目的就是給大家一個概念,現代的處理器架構已經比幾十年前的馮諾依曼體系復雜多了(各種box),里邊稍微值得關注的是Cbox ,Bbox ,這兩個組件是緩存控制器,負責非常核心的功能:緩存一致性。緩存一致性會在后續文章描述。
這張圖是intel多核體系架構(雙路)的緩存示意圖,每個core擁有自己的L1和L2緩存,屬于一個物理CPU的core共享L3緩存。不同cpu之間通過QPI交互L3數據。每個CPU有自己的內存控制器。對多核編程而言,緩存是非常重要的底層概念。
1.4 Linux 線程核綁定
這么多核具體到編程是如何使用的?
在linux平臺提供了核親和性機制,進程和線程都可以通過設置親和性綁定到不同的核心上。
進程版本:
#include <sched.h>
void setProcessToCPU(int _cpuID)
{
????cpu_set_t mask;
????cpu_set_t get;
?
????CPU_ZERO(&mask);
????CPU_SET(_cpuID, &mask);
?
????if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
????????cout << "set process affinity failed\n" << endl;
????}
????CPU_ZERO(&get);
????if (sched_getaffinity(0, sizeof(get), &get) < 0) {
????????cout << "get process affinity failed\n" << endl;
????}
}
?
線程版本:
#include <pthread.h>
#include <sched.h>
void setThreadToCPU(int _cpuID)
{
????cpu_set_t mask;
????cpu_set_t get;
?
????CPU_ZERO(&mask);
????CPU_SET(_cpuID, &mask);
?
????if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
????????cout << "set thread affinity failed\n" << endl;
????}
????CPU_ZERO(&get);
????if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
????????cout << "get thread affinity failed\n" << endl;
????}
}
?