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

打印 上一主题 下一主题

主题 916|帖子 916|积分 2748

在某些场景下,需要把程序绑定到指定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
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莫张周刘王

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表