C++多線程實(shí)現(xiàn)綁定CPU的方法詳解
Windows多線程
windows.h中提供了多線程解決方案,創(chuàng)建多線程的函數(shù)為
//返回值:一個(gè)HANDLE類型的值,表示線程的句柄,可用于等待線程等函數(shù) HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // 不用管,一般為NULL SIZE_T dwStackSize, // 堆棧大小,一般為0,表示默認(rèn)值 LPTHREAD_START_ROUTINE lpStartAddress, // 函數(shù)指針 __drv_aliasesMem LPVOID lpParameter, // 參數(shù)指針 DWORD dwCreationFlags, // 不用管,一般為0 LPDWORD lpThreadId // 線程id,一般設(shè)為NULL );
為了理解這個(gè)函數(shù),下面舉一個(gè)最簡(jiǎn)單的例子
#include<iostream>
#include<windows.h>
// 編寫了一個(gè)我的線程函數(shù)
DWORD WINAPI MyThread(LPVOID ps)
{
int *n = (int *)ps;
for (int i = 0; i < 3; ++i)
printf("執(zhí)行線程%d, i=%d\n", n[0], i);
return 0L;
}
int main()
{
// 創(chuàng)造線程
int id1 = 1, id2=2;
CreateThread(NULL, 0, MyThread, &id1, 0, NULL);
CreateThread(NULL, 0, MyThread, &id2, 0, NULL);
system("PAUSE");
return 0;
}
其中,MyThread是一個(gè)用于創(chuàng)造新線程的函數(shù),其輸入?yún)?shù)ps是一個(gè)LPVOID類型的指針,在參數(shù)傳入后,將這個(gè)指針轉(zhuǎn)為整形指針(int *),然后將其賦給另一個(gè)整形指針n,然后在for循環(huán)中引用這個(gè)整形指針。
在main函數(shù)中,通過CreateThread函數(shù)創(chuàng)建一個(gè)線程并執(zhí)行,其中執(zhí)行的函數(shù)為MyThread,傳入的參數(shù)為id1, id2的地址。執(zhí)行后的結(jié)果為
執(zhí)行線程2, i=0
執(zhí)行線程1, i=0
執(zhí)行線程1, i=1
執(zhí)行線程1, i=2
執(zhí)行線程2, i=1
執(zhí)行線程2, i=2
請(qǐng)按任意鍵繼續(xù). . .
windows調(diào)度與綁定CPU
作為成熟的操作系統(tǒng),Windows為了更加充分利用CPU,會(huì)動(dòng)態(tài)分配線程占用的CPU資源,以確保每個(gè)CPU核心不過累;另一方面,Intel作為成熟的CPU,為了充分考慮性能和能耗之間的均衡,當(dāng)CPU沒有滿負(fù)荷運(yùn)行的時(shí)候會(huì)自動(dòng)降頻。
這兩個(gè)合在一起就是,Windows動(dòng)態(tài)分配CPU核心,讓每個(gè)CPU都不過載;然后Intel動(dòng)態(tài)規(guī)劃能耗,讓每個(gè)核心都降頻。于是CPU的頻率越降越低,Windows占用的資源越來越少,于是性能越來越差。
上面這個(gè)描述當(dāng)然略顯夸張了,但道理是這么個(gè)道理,為了驗(yàn)證這一點(diǎn),可以將上面的MyThread函數(shù)稍作改動(dòng),
DWORD WINAPI MyThread(LPVOID ps)
{
int* n = (int*)ps;
int cpu = GetCurrentProcessorNumber();
for (int i = 0; i < 5; ++i) {
printf("在CPU%d上執(zhí)行線程%d, i=%d\n", cpu, n[0], i);
Sleep(100);
}
return 0L;
}這樣就可以查看每次執(zhí)行線程時(shí)所使用的CPU,發(fā)現(xiàn)每次運(yùn)行時(shí)使用的CPU是隨機(jī)的。
通過windows.h中的SetThreadAffinityMask來手動(dòng)分配CPU,使用方法非常簡(jiǎn)單
int main()
{
// 創(chuàng)造線程
int id1 = 1, id2=2;
auto th1 = CreateThread(NULL, 0, MyThread, &id1, 0, NULL);
SetThreadAffinityMask(th1, 0x01);
auto th2 = CreateThread(NULL, 0, MyThread, &id2, 0, NULL);
SetThreadAffinityMask(th2, 0x02);
// 記得等待線程結(jié)束
system("PAUSE");
return 0;
}效果如下
在CPU0上執(zhí)行線程1, i=0
在CPU1上執(zhí)行線程2, i=0
請(qǐng)按任意鍵繼續(xù). . . 在CPU1上執(zhí)行線程2, i=1
在CPU0上執(zhí)行線程1, i=1
在CPU0上執(zhí)行線程1, i=2
在CPU1上執(zhí)行線程2, i=2
在CPU1上執(zhí)行線程2, i=3
在CPU0上執(zhí)行線程1, i=3
在CPU1上執(zhí)行線程2, i=4
在CPU0上執(zhí)行線程1, i=4
到此這篇關(guān)于C++多線程實(shí)現(xiàn)綁定CPU的方法詳解的文章就介紹到這了,更多相關(guān)C++多線程綁定CPU內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言中K-means算法實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言中K-means算法的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
VisualStudio2019構(gòu)建C/C++靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)dll的問題 附源碼
這篇文章主要介紹了VisualStudio2019構(gòu)建C/C++靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)(dll)(文末附源碼),本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
C++服務(wù)器和客戶端交互的項(xiàng)目實(shí)踐
本文主要介紹了C++服務(wù)器和客戶端交互的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
C++實(shí)現(xiàn)尋找最低公共父節(jié)點(diǎn)的方法
這篇文章主要介紹了C++實(shí)現(xiàn)尋找最低公共父節(jié)點(diǎn)的方法,是數(shù)據(jù)結(jié)構(gòu)中二叉樹的一個(gè)經(jīng)典算法,有一定的借鑒價(jià)值,需要的朋友可以參考下2014-09-09
基于VC 6.0使用C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊
這篇文章主要為大家詳細(xì)介紹了基于VC 6.0使用C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
詳解如何在C/C++中測(cè)量一個(gè)函數(shù)或功能的運(yùn)行時(shí)間
本文算是一個(gè)比較完整的關(guān)于在 C/C++ 中測(cè)量一個(gè)函數(shù)或者功能的總結(jié),最后會(huì)演示三種方法的對(duì)比,文章通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12

