在我的系统上,SetThreadAffinityMask
似乎可以缓解这个问题。仍然存在一些不平衡,显然是由于一个核心的可用时间少于另一个,但并不那么严重。
Windows 似乎不愿意在内核之间移动这些线程;他们很少在第一秒左右改变核心。如果线程在内核之间分布不均,则线程时间反映了这一点。
这是我用来尝试亲和掩码的代码:
#include <Windows.h>
#include <stdio.h>
DWORD WINAPI ThreadStart(LPVOID arg)
{
DWORD pn1, pn2;
printf("Thread %u on processor %u\n", GetThreadId(GetCurrentThread()), pn1 = GetCurrentProcessorNumber());
// The problem comes back if you enable this line
// SetThreadAffinityMask(GetCurrentThread(), -1);
for (;;)
{
for (int i = 0; i < 10000; i++);
pn2 = GetCurrentProcessorNumber();
if (pn2 != pn1)
{
pn1 = pn2;
printf("Thread %u on processor %u\n", GetThreadId(GetCurrentThread()), pn1);
}
}
return 0;
}
int main(int argc, char ** argv)
{
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
SYSTEM_INFO si;
GetSystemInfo(&si);
for (DWORD i = 0; i < si.dwNumberOfProcessors; i++)
{
SetThreadAffinityMask(CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL), 1 << i);
SetThreadAffinityMask(CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL), 1 << i);
}
Sleep(INFINITE);
return 0;
}
这种方法似乎也缓解了这个问题,尽管可能没有那么有效:
#include <Windows.h>
#include <stdio.h>
DWORD WINAPI ThreadStart(LPVOID arg)
{
for (;;);
return 0;
}
int main(int argc, char ** argv)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
for (DWORD i = si.dwNumberOfProcessors * 2; i > 0; i--)
{
CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL);
}
for (;;)
{
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
Sleep(100);
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
}
return 0;
}
我怀疑我们正在研究一种基于低优先级线程不需要公平调度的假设而设计的节能措施。(可以说,将线程或进程设置为低优先级表示“我不在乎我得到多少 CPU。”)