在Win32上,如何将线程移动到另一个CPU内核?

时间:2020-03-06 15:02:39  来源:igfitidea点击:

我想确保将线程移动到特定的CPU内核,并且调度程序永远不能将其从该线程中移出。

有一个SetThreadAffinityMask()调用,但没有GetThreadAffinityMask()。

我之所以需要这样做,是因为如果调度程序将该线程移至另一个CPU,则高分辨率计时器会陷入混乱。

解决方案

我们可能应该只使用SetThreadAffinityMask并相信它正在工作。

MSDN

肯说了什么。但是,如果我们不相信它能正常工作,则可以再次调用SetThreadAffinityMask,并确认返回值与我们期望的掩码匹配。 (但是,当然,如果我们不信任该函数,那么我们将无法信任第二个调用...)

不要对GetProcessAffinityMask的存在感到困惑。该函数不存在以验证SetProcessAffinityMask是否正常工作,但是例如因此,我们可以构造线程亲和力,它是进程亲和力的子集。

只要看一下返回值并确认它不是0,就可以了。

不需要GetThreadAffinityMask。只需获取GetProcessAffinityMask的值,关闭一些位,然后调用SetThreadAffinityMask即可。线程继承了进程的亲和力掩码,并且由于它们的亲和力在控制之下,因此我们已经知道线程的亲和力掩码(这是我们将其设置为的掩码)。

如果我们可以调用一个返回数字以指示线程正在运行的CPU的函数,而不使用亲和力,则该函数返回后,答案通常会是错误的。因此,除了以提高的IRQL运行的内核代码之外,检查SetThreadAffinityMask()返回的掩码与我们将要达到的目标差不多。

听起来我们正在尝试解决" RDTSC"时钟偏斜问题。如果我们直接使用" RDTSC"指令,请考虑改为调用" QueryPerformanceCounter()":

  • 如果芯片组支持并且在系统的ACPI表中,则Windows Vista上的QueryPerformanceCounter()将使用HPET。
  • 如果我们调用" QueryPerformanceCounter()",则使用AMD处理器驱动程序的基于AMD的系统将主要补偿多核时钟偏差,但是对于直接使用" RDTSC"的应用程序则无济于事。 AMD双核优化器是针对直接使用" RDTSC"的应用程序的一种黑客工具,但是如果由于C1时钟斜升(在C1电源状态下时钟速度降低)而导致时钟偏斜量发生了变化,那么我们仍然可以时钟偏斜。而且这些实用程序可能并不十分普及,因此将亲和力与QueryPerformanceCounter()一起使用仍然是一个好主意。