1. 控制调用进程的亲和性
void SetSchedAffinity(ULONGLONG cpuMask)
{
HANDLE handle = GetCurrentProcess();
// 需要从临时的进程句柄转换成真正的进程句柄,并用完后关闭相应句柄
HANDLE hCurHandle = nullptr;
DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &hCurHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
DWORD_PTR eErr = SetProcessAffinityMask(hCurHandle, cpuMask);
CloseHandle(hCurHandle);
}
2. 控制调用线程的亲和性
void SetThreadAffinity(ULONGLONG cpuMask)
{
DWORD_PTR dwMask = cpuMask;
HANDLE handle = GetCurrentThread();
// 需要从临时的线程句柄转换成真正的线程句柄,并用完后关闭相应句柄
HANDLE hCurHandle = nullptr;
DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &hCurHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
DWORD_PTR eErr = SetThreadAffinityMask(hCurHandle, dwMask);
CloseHandle(hCurHandle);
}
这两个函数在Windows下是可以的,Linux下也有相应的函数。
现阶段最多只能支持64核的。ULONGLONG 每一个bit代表一个核心。
在Windows11下,有支持超过64核心的函数进行处理。
3. 测试代码:
测试线程
unsigned int ThreadTest(LPVOID pParam)
{
ULONGLONG cpuMask = (ULONGLONG)pParam;
IDPSetThreadAffinity(cpuMask);
while (1)
{
}
return 1;
}
// 设置当前进程在前五个核心上运行
IDPSetSchedAffinity(0, 0, 0x000000000000001f); // 进程在前五个核心上运行
启动四个线程,分别在不同核上运行,最后设置主线程在第五个核心上运行。
void OnTest()
{
AfxBeginThread(ThreadTest, (LPVOID)1); // 第一个核心
AfxBeginThread(ThreadTest, (LPVOID)2); // 第二个核心
AfxBeginThread(ThreadTest, (LPVOID)4); // 第三个核心
AfxBeginThread(ThreadTest, (LPVOID)8); // 第四个核心
IDPSetThreadAffinity(0x0000000000000010); // 当前线程在第五个核心
}
4. 注意
进程的亲和性大于线程的亲和性,即如果进程的亲和性控制在前五个,即使线程设置在其他核上,操作系统会将线程控制在进程设置的范围内。