翼度科技»论坛 编程开发 .net 查看内容

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

5

主题

5

帖子

15

积分

新手上路

Rank: 1

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

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

SetThreadAffinityMask的定义如下:
  1. DWORD_PTR SetThreadAffinityMask(
  2.   [in] HANDLE    hThread,
  3.   [in] DWORD_PTR dwThreadAffinityMask
  4. );
复制代码
从函数的定义看需要传递两个参数:

  • 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
  1. [DllImport("kernel32.dll")]
  2. static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask);
  3. [DllImport("kernel32.dll")]
  4. static extern IntPtr GetCurrentThread();
复制代码
由于dwThreadAffinityMask的值是按照2n的指数递增,与通常习惯指定第n个核心不符,并且不同的设备CPU核心数不一样,指定CPU核心时可能超出CPU核心数量,因此可以对指定CPU核心做个简单的处理:
[code]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

举报 回复 使用道具