在某些场景下,需要把程序绑定到指定CPU核心提高执行效率。通过微软官方文档查询到Windows提供了两个Win32函数:SetThreadAffinityMaskSetProcessAffinityMask 为指定线程和进程设置处理器关联掩码。通俗的讲就是在指定的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一样,也是需要传递两个参数,只不过第一个参数传递的是线程的句柄。

小结

在某些场景可以通过SetThreadAffinityMaskSetProcessAffinityMask 提高程序执行效率,主要是基于以下几个原因:

  • 提高性能:通过将线程绑定到特定的处理器,可以减少线程在不同处理器之间的切换开销,尤其是在多核系统中,有助于提升程序的执行效率。
  • 避免缓存抖动:确保线程始终在同一个处理器上运行,可以减少缓存未命中,因为相关的数据更可能保留在该处理器的高速缓存中。
  • 实时系统和并发控制:在需要严格控制线程执行位置的场景下,比如实时系统或者某些并发控制策略中,通过设定处理器关联可以满足特定的调度需求。

    需要注意的是,SetThreadAffinityMask和SetProcessAffinityMask并不是独占CPU核心,如果关联的CPU核心本身负载就很高,这个时候程序执行效率反而会降低。

Windows下绑定线程到指定的CPU核心的更多相关文章

  1. windows下绑定线程(进程)到指定的CPU核心

    一个程序指定到单独一个CPU上运行会比不指定CPU运行时快.这中间主要有两个原因:1)CPU切换时损耗的性能.2)Intel的自动降频技术和windows的机制冲突:windows有一个功能是平衡负载 ...

  2. SetThreadAffinityMask windows下绑定线程(进程)到指定的CPU核心

    原帖地址:https://www.cnblogs.com/lvdongjie/p/4476766.html 一个程序指定到单独一个CPU上运行会比不指定CPU运行时快.这中间主要有两个原因:1)CPU ...

  3. WINDOWS下绑定ARP绑定网关

    一.WINDOWS下绑定ARP绑定网关步骤一:在能正常上网时,进入MS-DOS窗口,输入命令:arp -a,查看网关的IP对应的正确MAC地址, 并将其记录下来.注意:如果已经不能上网,则先运行一次命 ...

  4. windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码

    我的一个java程序偶尔会出现cpu占用很高的情况 一直不知道什么原因 今天终于抽时间解决了 系统是win2003 jvisualvm 和 jconsole貌似都只能看到总共占用的cpu 看不到每个线 ...

  5. windows下揪出java程序占用cpu很高的线程

    背景 天天搞java,这些监控也都知道,用过,但也没往细里追究.因为也没碰见这种问题,这次还是静下来走一遍流程吧.与网上基本一致,不过我区分了下linux和windows的不一样.我感觉基本是程序写成 ...

  6. Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity) 转

    硬件中断发生频繁,是件很消耗 CPU 资源的事情,在多核 CPU 条件下如果有办法把大量硬件中断分配给不同的 CPU (core) 处理显然能很好的平衡性能.现在的服务器上动不动就是多 CPU 多核. ...

  7. Windows下caffe安装详解(仅CPU)

    本文大多转载自 http://blog.csdn.net/guoyk1990/article/details/52909864,加入部分自己实战心得. 1.环境:windows 7\VS2013 2. ...

  8. windows下多Python环境指定pip安装模块到对应Python环境下

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿在windows下装了2套Python,一套是直接安装的Pytho ...

  9. Windows下POSIX线程编程(pThread)环境搭建

    系统: Windows 编辑器:codeblocks13.12 1. 简介: Windows有一个叫 POSIX Threads for Win32 的开源项目给出了一个功能比较完善的Windows下 ...

  10. windows下利用线程池完成多任务的分配和运行

    在做项目的过程中有时候为了提升效率,用了多线程的方法来对任务进行分割和应用,后来发现,采用线程池的方法能更好的利用线程资源来计算任务,网上有很多关于如何运行线程池的例子,msdn上也给出了对应的例子: ...

随机推荐

  1. 那位拿了多个Offer的大佬分享了最新Go面经

    和大家分享一下我们 Go就业训练营 和 升职加薪星球 中战友们投稿的真实面经. 这是第一篇,计划还会再更新4篇最新Go面经,都是拿到Offer的那种! 欢迎大家关注我的账号,关注之后不迷路. 先秀战绩 ...

  2. KingbaseES 如何查看表的创建时间

    前言 在oracle数据库中,我们可以查看数据字典dba_objects得到表的创建时间.在Kingbase中如何查看表的创建时间呢?Kingbase数据库中无法通过数据字典查看有关信息,但可以通过其 ...

  3. 第十三届蓝桥杯大赛软件赛省赛【Java 大学B 组】试题C: 字符统计

    1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String args[]) { 5 Sca ...

  4. 【已解决】linux安装mysql依赖包(mysql-community-common-5.7.35-1.el7.x86_64)冲突

    错误信息: 软件包 mysql-community-common-5.7.35-1.el7.x86_64 (比 mysql-community-common-5.7.28-1.el7.x86_64 还 ...

  5. SQL 递归核心思想(递归思维)

    目前很缺递归思维,主要是算法代码写得少,本篇记录下以 PostgreSQL 代码举例(主要是非常喜欢这款性能小钢炮数据库). 树状查询不多说,很简单大家基本都会,主要讲 cte 代码递归实现不同需求. ...

  6. #树状数组#洛谷 4113 [HEOI2012]采花

    题目 分析 与HH的项链类似 离线处理询问,按右端点排序,维护最近的颜色和第二近的颜色,修改以第二近的颜色为准 换句话说,若最近颜色的位置为\(pos2\),第二近颜色的位置为\(pos1\) 加入一 ...

  7. #Splay#洛谷 1486 [NOI2004]郁闷的出纳员

    题目 分析 考虑加减工资直接打标记,查询第\(k\)多可以用平衡树, 删除有点恶心,这里考虑Splay,将需要删除的部分的后继splay到根节点并将左子树断边 代码 #include <cstd ...

  8. JDK14的新特性:JFR,JMC和JFR事件流

    目录 简介 JFR JMC 创建JFR 分析JFR JFR事件 JFR事件流 总结 JDK 14的新特性:JFR,JMC和JFR事件流 简介 Java Flight Recorder(JFR)是JVM ...

  9. OpenHarmony 官网文档有哪些上新?下篇:设备开发文档上新

    为了方便社区开发者更易获取 OpenAtom OpenHarmony(以下简称"OpenHarmony")相关文档,暨上篇应用开发文档上新内容,SIG Docs  小组同步准备了设 ...

  10. Windows wsl2支持systemd

    背景 很多Linux发行版都是使用systemd来管理程序进程,但是在WSL中默认是用init来管理进程的. 为了符合长久的使用习惯,且省去不必要的学习成本,就在WSL的发行版(我这里安装的是Ubun ...