Windows下绑定线程到指定的CPU核心
在某些场景下,需要把程序绑定到指定CPU核心提高执行效率。通过微软官方文档查询到Windows提供了两个Win32函数:SetThreadAffinityMask和SetProcessAffinityMask 为指定线程和进程设置处理器关联掩码。通俗的讲就是在指定的CPU核心上执行线程或者进程。
这里的CPU核心指的是逻辑核心,而非物理核心。
SetThreadAffinityMask
SetThreadAffinityMask函数定义
SetThreadAffinityMask的定义如下:
DWORD_PTR SetThreadAffinityMask(
[in] HANDLE hThread,
[in] 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
[DllImport("kernel32.dll")]
static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThread();
由于dwThreadAffinityMask的值是按照$2^n$的指数递增,与通常习惯指定第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 << lpIdx;
return cpuLogicalProcessorId;
}
接下来就可以进行测试了
ulong LpId = SetCpuID((int)lpIdx);
SetThreadAffinityMask(GetCurrentThread(), new UIntPtr(LpId));
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
for (int j = 0; j < 1000000; j++)
{
int _data = j;
}
}
stopwatch.Stop();
Console.WriteLine("运行时间: " + stopwatch.ElapsedMilliseconds.ToString());
效果如图如下:

SetProcessAffinityMask
SetProcessAffinityMask与SetThreadAffinityMask非常相似,不同的是其作用于整个进程,可以决定进程内的所有线程共同运行在指定的处理器上。
函数定义如下:
BOOL SetProcessAffinityMask(
[in] HANDLE hProcess,
[in] DWORD_PTR dwProcessAffinityMask
);
和SetThreadAffinityMask一样,也是需要传递两个参数,只不过第一个参数传递的是线程的句柄。
小结
在某些场景可以通过SetThreadAffinityMask和SetProcessAffinityMask 提高程序执行效率,主要是基于以下几个原因:
- 提高性能:通过将线程绑定到特定的处理器,可以减少线程在不同处理器之间的切换开销,尤其是在多核系统中,有助于提升程序的执行效率。
- 避免缓存抖动:确保线程始终在同一个处理器上运行,可以减少缓存未命中,因为相关的数据更可能保留在该处理器的高速缓存中。
- 实时系统和并发控制:在需要严格控制线程执行位置的场景下,比如实时系统或者某些并发控制策略中,通过设定处理器关联可以满足特定的调度需求。
需要注意的是,SetThreadAffinityMask和SetProcessAffinityMask并不是独占CPU核心,如果关联的CPU核心本身负载就很高,这个时候程序执行效率反而会降低。
Windows下绑定线程到指定的CPU核心的更多相关文章
- windows下绑定线程(进程)到指定的CPU核心
一个程序指定到单独一个CPU上运行会比不指定CPU运行时快.这中间主要有两个原因:1)CPU切换时损耗的性能.2)Intel的自动降频技术和windows的机制冲突:windows有一个功能是平衡负载 ...
- SetThreadAffinityMask windows下绑定线程(进程)到指定的CPU核心
原帖地址:https://www.cnblogs.com/lvdongjie/p/4476766.html 一个程序指定到单独一个CPU上运行会比不指定CPU运行时快.这中间主要有两个原因:1)CPU ...
- WINDOWS下绑定ARP绑定网关
一.WINDOWS下绑定ARP绑定网关步骤一:在能正常上网时,进入MS-DOS窗口,输入命令:arp -a,查看网关的IP对应的正确MAC地址, 并将其记录下来.注意:如果已经不能上网,则先运行一次命 ...
- windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码
我的一个java程序偶尔会出现cpu占用很高的情况 一直不知道什么原因 今天终于抽时间解决了 系统是win2003 jvisualvm 和 jconsole貌似都只能看到总共占用的cpu 看不到每个线 ...
- windows下揪出java程序占用cpu很高的线程
背景 天天搞java,这些监控也都知道,用过,但也没往细里追究.因为也没碰见这种问题,这次还是静下来走一遍流程吧.与网上基本一致,不过我区分了下linux和windows的不一样.我感觉基本是程序写成 ...
- Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity) 转
硬件中断发生频繁,是件很消耗 CPU 资源的事情,在多核 CPU 条件下如果有办法把大量硬件中断分配给不同的 CPU (core) 处理显然能很好的平衡性能.现在的服务器上动不动就是多 CPU 多核. ...
- Windows下caffe安装详解(仅CPU)
本文大多转载自 http://blog.csdn.net/guoyk1990/article/details/52909864,加入部分自己实战心得. 1.环境:windows 7\VS2013 2. ...
- windows下多Python环境指定pip安装模块到对应Python环境下
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿在windows下装了2套Python,一套是直接安装的Pytho ...
- Windows下POSIX线程编程(pThread)环境搭建
系统: Windows 编辑器:codeblocks13.12 1. 简介: Windows有一个叫 POSIX Threads for Win32 的开源项目给出了一个功能比较完善的Windows下 ...
- windows下利用线程池完成多任务的分配和运行
在做项目的过程中有时候为了提升效率,用了多线程的方法来对任务进行分割和应用,后来发现,采用线程池的方法能更好的利用线程资源来计算任务,网上有很多关于如何运行线程池的例子,msdn上也给出了对应的例子: ...
随机推荐
- 【Oracle】通过LogMiner实现Oracle数据同步迁移
写在前面 最近在研究如何实现Oracle数据库之间的数据同步,网上的资料确实比较少.最好用的Oracle数据库同步工具是:GoldenGate ,而GoldenGate是要收费的.那么还有什么好的办法 ...
- 前端ajax调用后端下载Excel模板流,解决输出乱码等问题
JavaScript方法function importTemplate() { $.ajax({ url: "/importTemplate", type: "get&q ...
- stm32F103 移植Free RTOS
stm32F103 移植Free RTOS 1. 下载FreeRTOS 源码 [官网下载] (http://www.freertos.org) [代码托管网站下载] (https://sourcefo ...
- #线段树合并#洛谷 3224 [HNOI2012]永无乡
题目 分析 和主席树不同的是,线段树合并后原树的信息不会保留, 这样就保证空间和常数都比较小,这题比较裸,直接上代码 代码 #include <cstdio> #include <c ...
- 为什么 L1 正则化能做特征选择而 L2 正则化不能
假设我们的模型只有一个参数 \(w\),损失函数为 \(L(w)\),加入 L1 和 L2 正则化后的损失函数分别记为 \(J_1(w), J_2(w)\): \[\begin{gathered} J ...
- 机器学习&深度学习 操作tips
1. 在运行程序时,报错如下: usage: run.py [-h] --model MODEL [--embedding EMBEDDING] [--word WORD] run.py: error ...
- 第十八篇:Django进级
一.Django工程创建 二.Django 的 CBV和FBV 三.模板语言循环字典 四.Django基于正则表达式的URL 五.Django对应的路由名称 六.Django路由分发 七.Django ...
- 鸿蒙HarmonyOS实战-ArkUI组件(页面路由)
一.路由导航 路由导航是指在应用程序中通过路径导航定位到特定页面的过程.路由导航的实现通常采用路由器(router)来进行管理,路由器根据路径的不同值将用户请求导向到不同的页面. 在HarmonyOS ...
- redis 简单整理——阻塞问题[二十五]
前言 简单介绍一下redis的阻塞问题. 正文 Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成 的.当Redis用于高并发场景时,这条线程就变成了它的生命线.如果出现 阻塞,哪怕是 ...
- ef 查询生成语句的几种方式
前言 整理一下ef 如何查看生成sql 语句的,现在有ef core 了,统一整理一下. 正文 方式如下: 数据库监听 这是一种推荐方式,因为调试和代码分开,不会有影响. 然后连接: 然后可以进行一些 ...