鉴竖 发表于 2024-4-29 20:15:19

Windows下绑定线程到指定的CPU核心

在某些场景下,需要把程序绑定到指定CPU核心提高执行效率。通过微软官方文档查询到Windows提供了两个Win32函数:SetThreadAffinityMask和SetProcessAffinityMask 为指定线程和进程设置处理器关联掩码。通俗的讲就是在指定的CPU核心上执行线程或者进程。
这里的CPU核心指的是逻辑核心,而非物理核心。
SetThreadAffinityMask

SetThreadAffinityMask用于设置指定线程的处理器关联掩码,从而实现线程对处理器的绑定。
SetThreadAffinityMask函数定义

SetThreadAffinityMask的定义如下:
DWORD_PTR SetThreadAffinityMask(
HANDLE    hThread,
DWORD_PTR dwThreadAffinityMask
);从函数的定义看需要传递两个参数:

[*]hThread:指向要设置处理器关联的线程句柄。如果是想设置当前线程的关联掩码,可以使用 GetCurrentThread() 函数获取句柄。
[*]dwThreadAffinityMask:处理器的关联掩码。是一个DWORD_PTR类型的值,长度共8个字节(64bit),每一bit代表一个cpu核。
如果需要支持超过64核的CPU时,则需要使用SetThreadGroupAffinity函数
为了更清晰的表达dwThreadAffinityMask的含义,下边用二进制数表示该值。比如,需要把线程绑定到
第0个核:则dwThreadAffinityMask=0B_0001;(0x01)
第1个核:则dwThreadAffinityMask=0B_0010;(0x02)
第2个核:则dwThreadAffinityMask=0B_0100;(0x04)
第3个核:则dwThreadAffinityMask=0B_1000;(0x08)
……
如果要绑定到多个cpu核心,比如绑定到第1和2个cpu核时,dwThreadAffinityMask=0B_0110,对应的十六进制数也就是0x06。
调用示例

首先引入Win32API

static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask);


static extern IntPtr GetCurrentThread();由于dwThreadAffinityMask的值是按照2n的指数递增,与通常习惯指定第n个核心不符,并且不同的设备CPU核心数不一样,指定CPU核心时可能超出CPU核心数量,因此可以对指定CPU核心做个简单的处理:
static ulong SetCpuID(int lpIdx){    ulong cpuLogicalProcessorId = 0;    if (lpIdx < 0 || lpIdx >= System.Environment.ProcessorCount)    {      lpIdx = 0;    }    //通过移位运算转换lgidx->dwThreadAffinityMask:0->1,1->2,2->4,3->8,……    cpuLogicalProcessorId |= 1UL
页: [1]
查看完整版本: Windows下绑定线程到指定的CPU核心