原帖地址:https://www.cnblogs.com/lvdongjie/p/4476766.html
一個程序指定到單獨一個CPU上運行會比不指定CPU運行時快。這中間主要有兩個原因:
1)CPU切換時損耗的性能。
2)Intel的自動降頻技術和windows的機制沖突:windows有一個功能是平衡負載,可以將一個線程在不同時間分配到不同CPU,從而使得每一個CPU不“過累”。然而,Inter又有一個技術叫做SpeedStep,當一個CPU沒有滿負荷運行時自動降頻從而達到節能減排的目的。這兩個功能實際是沖突的:一個程序被分配到多個CPU協同工作->每個CPU都不是滿載->每個CPU都會降頻->windows發現每個CPU性能都降低了,因此程序執行速度也降低了。
因此,將線程(進程)綁定到指定CPU核心,從而不讓windows自作主張幫我們分散任務,從而提高單線程效率是很有必要的。有兩種方法實現綁定進程到指定CPU:
1)手工調節:在資源管理器的進程里面,設置相關性,可以設置進程到某個或者某些指定的CPU核心。
這種方法最簡便,同樣是最優效率的,因為你可以根據當前CPU的負載情況進行選擇。
2)代碼自動調節:
參考:http://www.cnblogs.com/kex1n/archive/2011/05/09/2040924.html
具體函數為:
1
|
DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask);
|
其中,第一個參數為線程句柄,第二個參數為一個mask。
如果要知道當前線程的句柄,可以通過函數:GetCurrentThread()得到。否則,在創建多線程的時候,也同樣可以得到創建的線程的句柄。
第二個參數為mask,可取值為0~2^31(32位)和0~2^63(64位),每一位代表每一個CPU是否使用。
比如,你要指定進程到第0個CPU上,則mask=0×01
第1個CPU:mask=0×02
第2個CPU:mask=0×04 (注意不是0×03)
第3個CPU:mask=0×08
以此類推。
如果要指定多個CPU:
比如第0、1個:mask=0×03
第1、2個:mask=0×06
以此類推。
如果CPU個數不足,則會進行取模操作。比如一共4個CPU,則mask=0×0010則和0×01一樣。
這種方法的好處是多線程時不用每次都手動選擇CPU,缺點是萬一選到的CPU負載很高,那么程序執行速度就慢了(英雄所見略同所以大家都搶到同一個CPU去了么~~)
效果如下圖所示:
還有一個實用的函數來獲取當前CPU的核心數量:
1
2 3 |
SYSTEM_INFO info;
GetSystemInfo(&info); printf("Number of processors: %d.\n", info.dwNumberOfProcessors); |
輸出的是邏輯核心數量,比如i3處理器就是雙核心四線程,輸出4。i5處理器是四核心四線程,輸出也是4。
這樣就可以方便的知道當前系統一共有多少個CPU了,同時也方便了線程數選擇。
===============================================================
該函數中的h T h r e a d參數用於指明要限制哪個線程, dwThreadAffinityMask用於指明該線程能夠在哪個CPU上運行。
dwThreadAffinityMask必須是進程的親緣性屏蔽的相應子集。返回值是線程的前一個親緣性屏蔽。
因此,若要將3個線程限制到CPU1、2和3上去運行,可以這樣操作:
//Thread 0 can only run on CPU 0. SetThreadAffinityMask(hThread0, 0x00000001); //第0位是1 //Threads 1, 2, 3 run on CPUs 1, 2, 3.//第1 2 3位是1 SetThreadAffinityMask(hThread1, 0x00000002); SetThreadAffinityMask(hThread2, 0x00000003); SetThreadAffinityMask(hThread3, 0x00000004);
參考地址:https://blog.csdn.net/johnny710vip/article/details/23708241