CPU亲合力(CPU Affinity)

【性能优化点滴】【优秀三方库研读】odygrd/quill 涉及到的 CPU 亲和性(CPU Affinity)的作用详解 CPU 亲和性是指 将线程或进程绑定到特定的CPU核心上运行 的技术。通过设置亲和性,可以控制线程在哪些CPU核心上执行 阅读详情

CPU Affinity

作者: Robert Love   翻译:normalnotebook
Bind specific processes to specific processors with a new system call.
使用新的系统调用,可以将一个进程绑定到一个特定的CPU上运行。

The ability in Linux to bind one or more processes to one or more processors, called CPU affinity, is a long-requested feature. The idea is to say ``always run this process on processor one'' or ``run these processes on all processors but processor zero''. The scheduler then obeys the order, and the process runs only on the allowed processors.

 

       CPU亲合力就是指在Linux中能够将一个或多个进程绑定到一个或多个处理器上运行,这是期待已久的特性。也就是说:“在1号处理器上一直运行该程序”或者是“在所有的处理器上运行这些程序,而不是在0号处理器上运行”。然后,调度器将遵循该规则,程序仅仅运行在允许的处理器上。

Other operating systems, such as Windows NT, have long provided a system call to set the CPU affinity for a process. Consequently, demand for such a system call in Linux has been high. Finally, the 2.5 kernel introduced a set of system calls for setting and retrieving the CPU affinity of a process.

 

        其他类型的操作系统,比如Windows NT,很早以前就开始提供系统调用,用于设置应用程序的CPU亲合力。因此,要求Linux也提供这样的系统调用的呼声日益高涨。最终在2.5内核中,引入了一套系统调用用于设置和获取某个进程的CPU亲合力特性。

In this article, I look at the reasons for introducing a CPU affinity interface to Linux. I then cover how to use the interface in your programs. If you are not a programmer or if you have an existing program you are unable to modify, I cover a simple utility for changing the affinity of a given process using its PID. Finally, we look at the actual implementation of the system call.

 

       本文将探讨CPU亲合力被引入到Linux中的动机,以及在应用程序中如何使用亲合力接口。假如你不是一个程序员或者你拥有一个程序,但又不想修改它,那么我将运用一套简单的工具,通过PID改变给定进程的亲合力。最后,我们将探讨亲合力系统调用的具体实现原理。

Soft vs. Hard CPU Affinity

软亲合力 VS. 硬亲合力

There are two types of CPU affinity. The first, soft affinity, also called natural affinity, is the tendency of a scheduler to try to keep processes on the same CPU as long as possible. It is merely an attempt; if it is ever infeasible, the processes certainly will migrate to another processor. The new O(1) scheduler in 2.5 exhibits excellent natural affinity. On the opposite end, however, is the 2.4 scheduler, which has poor CPU affinity. This behavior results in the ping-pong effect. The scheduler bounces processes between multiple processors each time they are scheduled and rescheduled. Table 1 is an example of poor natural affinity; Table 2 shows what good natural affinity looks like.

 time 1time 2time 3time 4
Process ACPU 0CPU 1CPU 0CPU 1

Table 1. The Ping-Pong Effect

 time 1time 2time 3time 4
Process ACPU 0CPU 0CPU 0CPU 0

Table 2. Good Affinitiy

Hard affinity, on the other hand, is what a CPU affinity system call provides. It is a requirement, and processes must adhere to a specified hard affinity. If a processor is bound to CPU zero, for example, then it can run only on CPU zero.

Why One Needs CPU Affinity

Before we cover the new system calls, let's discuss why anyone would need such a feature. The first benefit of CPU affinity is optimizing cache performance. I said the O(1) scheduler tries hard to keep tasks on the same processor, and it does. But in some performance-critical situations--perhaps a large database or a highly threaded Java server--it makes sense to enforce the affinity as a hard requirement. Multiprocessing computers go through a lot of trouble to keep the processor caches valid. Data can be kept in only one processor's cache at a time. Otherwise, the processor's cache may grow out of sync, leading to the question, who has the data that is the most up-to-date copy of the main memory? Consequently, whenever a processor adds a line of data to its local cache, all the other processors in the system also caching it must invalidate that data. This invalidation is costly and unpleasant. But the real problem comes into play when processes bounce between processors: they constantly cause cache invalidations, and the data they want is never in the cache when they need it. Thus, cache miss rates grow very large. CPU affinity protects against this and improves cache performance.

A second benefit of CPU affinity is a corollary to the first. If multiple threads are accessing the same data, it might make sense to bind them all to the same processor. Doing so guarantees that the threads do not contend over data and cause cache misses. This does diminish the performance gained from multithreading on SMP. If the threads are inherently serialized, however, the improved cache hit rate may be worth it.

The third and final benefit is found in real-time or otherwise time-sensitive applications. In this approach, all the system processes are bound to a subset of the processors on the system. The specialized application then is bound to the remaining processors. Commonly, in a dual-processor system, the specialized application is bound to one processor, and all other processes are bound to the other. This ensures that the specialized application receives the full attention of the processor.

Getting the New System Calls

The system calls are new, so they are not available yet in all systems. You need at least kernel 2.5.8-pre3 and glibc 2.3.1; glibc 2.3.0 supports the system calls, but it has a bug. The system calls are not yet in 2.4, but patches are available at www.kernel.org/pub/linux/kernel/people/rml/cpu-affinity.

Many distribution kernels also support the new system calls. In particular, Red Hat 9 is shipping with both kernel and glibc support for the new calls. Real-time solutions, such as MontaVista Linux, also fully support the new interface.

Affinity Masks

On most systems, Linux included, the interface for setting CPU affinity uses a bitmask. A bitmask is a series of n bits, where each bit individually corresponds to the status of some other object. For example, CPU affinity (on 32-bit machines) is represented by a 32-bit bitmask. Each bit represents whether the given task is bound to the corresponding processor. Count the bits from right to left, bit 0 to bit 31 and, thus, processor zero to processor 31. For example:

11111111111111111111111111111111 = 4,294,967,295

is the default CPU affinity mask for all processes. Because all bits are set, the process can run on any processor. Conversely:

00000000000000000000000000000001 = 1

is much more restrictive. Only bit 0 is set, so the process may run only on processor zero. That is, this affinity mask binds a process to processor zero.

Get it? What do the next two masks equal in decimal? What is the result of using them as the affinity mask of a process?

10000000000000000000000000000000
00000000000000000000000000000011

The first is equal to 2,147,483,648 and, because bit 31 is set, binds the process to processor number 31. The second is equal to 3, and it binds the process in question to processor zero and processor one.

The Linux CPU affinity interface uses a bitmask like that shown above. Unfortunately, C does not support binary constants, so you always have to use the decimal or hexadecimal equivalent. You may get a compiler warning for very large decimal constants that set bit 31, but they will work.

Using the New System Calls

With the correct kernel and glibc in hand, using the system calls is easy:

#define _GNU_SOURCE
#include <sched.h>
long
sched_setaffinity(pid_t pid, unsigned int len, 
                  unsigned long *user_mask_ptr);
long
sched_getaffinity(pid_t pid, unsigned int len,
                  unsigned long *user_mask_ptr);

The first system call is used to set the affinity of a process, and the second system call retrieves it.

In either system call, the PID argument is the PID of the process whose mask you wish to set or retrieve. If the PID is set to zero, the PID of the current task is used.

The second argument is the length in bytes of the CPU affinity bitmask, currently four bytes (32 bits). This number is included in case the kernel ever changes the size of the CPU affinity mask and allows the system calls to be forward-compatible with any changes; breaking syscalls is bad form, after all. The third argument is a pointer to the bitmask itself.

Let us look at retrieving the CPU affinity of a task:

unsigned long mask;
unsigned int len = sizeof(mask);
if (sched_getaffinity(0, len, &mask) < 0) {
    perror("sched_getaffinity");
    return -1;
    }
printf("my affinity mask is: %08lx/n", mask);

As a convenience, the returned mask is binary ANDed against the mask of all processors in the system. Thus, processors in your system that are not on-line have corresponding bits that are not set. For example, a uniprocessor system always returns 1 for the above call (bit 0 is set and no others).

Setting the mask is equally easy:

unsigned long mask = 7; /* processors 0, 1, and 2 */
unsigned int len = sizeof(mask);
if (sched_setaffinity(0, len, &mask) < 0) {
    perror("sched_setaffinity");
}

This example binds the current process to the first three processors in the system.

You then can call sched_getaffinity() to ensure the change took effect. What does sched_getaffinity() return for the above setup if you have only two processors? What if you have only one? The system call fails unless at least one processor in the bitmask exists. Using a mask of zero always fails. Likewise, binding to processor seven if you do not have a processor seven will fail.

It is possible to retrieve the CPU affinity mask of any process on the system. You can set the affinity of only the processes you own, however. Of course, root can set any process' affinity.

I Want a Tool!

If you are not a programmer, or if you cannot modify the source for whatever reason, you still can bind processes. Listing 1 is the source code for a simple command-line utility to set the CPU affinity mask of any process, given its PID. As we discussed above, you must own the process or be root to do this.

Listing 1. bind

Usage is simple; once you learn the decimal equivalent of the CPU mask, you need:

usage: bind pid cpu_mask

As an example, assume we have a dual computer and want to bind our Quake process (with PID 1600) to processor two. We would enter the following:

bind 1600 2



Getting Really Crafty

In the previous example, we bound Quake to one of the two processors in our system. To ensure top-notch frame rates, we need to bind all the other processes on the system to the other processor. You can do this by hand or by writing a crafty script, but neither is efficient. Instead, make use of the fact that CPU affinity is inherited across a fork(). All of a process' children receive the same CPU affinity mask as their parent.

Then, all we need to do is have init bind itself to one processor. All other processes, by nature of init being the root of the process tree and thus the superparent of all processes, are then likewise bound to the one processor.

The cleanest way to do this type of bind is to hack this feature into init itself and pass in the desired CPU affinity mask using the kernel command line. We can accomplish our goal with a simpler solution, though, without having to modify and recompile init. Instead, we can edit the system startup script. On most systems this is /etc/rc.d/rc.sysinit or /etc/rc.sysinit, the first script run by init. Place the sample bind program in /bin, and add these lines to the start of rc.sysinit:

/bin/bind 1 1
/bin/bind $ 1

These lines bind init (whose PID is one) and the current process to processor zero. All future processes will fork from one of these two processes and thus inherit the CPU affinity mask. You then can bind your process (whether it be a real-time nuclear control system or Quake) to processor one. All processes will run on processor zero except our special process (and any children), which will run on processor one. This ensures that the entire processor is available for our special process.

Kernel Implementation of CPU Affinity

Long before Linus merged the CPU affinity system calls, the kernel supported and respected a CPU affinity mask. There was no interface by which user space could set the mask.

Each process' mask is stored in its task_struct as an unsigned long, cpus_allowed. The task_struct structure is called the process descriptor. It stores all the information about a process. The CPU affinity interface merely reads and writes cpus_allowed.

Whenever the kernel attempts to migrate a process from one processor to another, it first checks to see if the destination processor's bit is set in cpus_allowed. If the bit is not set, the kernel does not migrate the process. Further, whenever the CPU affinity mask is changed, if the process is no longer on an allowed processor it is migrated to one that is allowed. This ensures the process begins on a legal processor and can migrate only to a legal processor. Of course, if it is bound to only a single processor, it does not migrate anywhere.

Conclusion

The CPU affinity interface introduced in 2.5 and back-ported elsewhere provides a simple yet powerful mechanism for controlling which processes are scheduled onto which processors. Users with more than one processor may find the system calls useful in squeezing another drop of performance out of their systems or for ensuring that processor time is available for even the most demanding real-time task. Of course, users with only one processor need not feel left out. They also can use the system calls, but they aren't going to be too useful.

CPU Affinity (CPU亲合力) 在Linux下进行多核编程的时候,通常要设置CPU的亲和力(Affinity)。下面通过讲解sched_setaffinity()和sched_getaffinity()函数以及CPU_ZERO()、CPU_SET()、CPU_CLR()、CPU_ISSET()对CPU的亲和力进行分析。 阅读详情

相关推荐

第四章、Isaacsim在GUI中构建机器人(3):添加摄像头和传感器

本节。

m0_47719040的博客 2495

Linux中CPU亲和性(affinity)

就是利用特殊的硬件指令,(一个核模拟出两个核?)让,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。我们常听到的双核四线程/四核八线程指的就是支持超线程技术的CPU.**物理CPU:**机器上安装的实际CPU, 比如说你的主板上安装了一个8核CPU,那么物理CPU个数就是1个,所以物理CPU个数就是主板上安装的CPU个数。**逻辑CPU:**一般情况,我们认为一颗CPU可以有多核,加上intel的超线程技术(HT), 可以在逻辑上再分一倍数量的CPU core出来;

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 4066

利用DRONEKIT-SITL + MAVPROXY + QGroundControl模拟飞行

dronekit: 一种用于无人机控制的python库。 dronekit-sitl:一种本地仿真工具,相当于本地虚拟化了一个无人机。 mavproxy:数据转发软件(类似于插线板的感觉,一个输入,多个相同的输出)。打开一个Anaconda prompt 首先激活相应的环境 然后运行如下命令: 保持2中的Anaconda prompt处于运行状态,另打开一个Anaconda prompt窗口,运行如下命令: tcp:127.0.0.1:5760: SITL默认端口,作为mavproxy的输入,把输入数据转发

Done___的博客 4344

一文说明 CPU亲和性(CPU Affinity)

就是利用特殊的硬件指令,把两个逻辑内核(CPU core)模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。我们常听到的双核四线程/四核八线程指的就是支持超线程技术的CPU.:机器上安装的实际CPU, 比如说你的主板上安装了一个8核CPU,那么物理CPU个数就是1个,所以物理CPU个数就是主板上安装的CPU个数。

usstmiracle的博客 2767

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距 关键词:语音提示盲人拐杖 整点报时 超声波测距拐杖

LS840233684的博客 2047

WPS JS宏智能识别代码段并设置样式(完整可用版)

之前,我们已经经历了多次迭代,解决了许多问题,比如识别代码块、处理多行导入、调整样式等。现在他们需要一份全面的文档来解释整个代码的结构和工作原理。(5)智能行分析(含URL和注解检测优化)function analyzeLineEnhanced(rawText,trimmedText,codeSymbols,codePatterns, singleLinePatterns)该解决方案在保持高性能的同时,提供了良好的可扩展性,能够适应不同组织的代码规范需求,是WPS生态中专业文档处理的创新实践。

搏博的专栏 1828

手机上的算法优化 —— CPU绑定(CPU affinity)

【前言】 写了一段时间博客发现,以实际例子来说明一件事,可能会让读者更容易理解那些知识。 从今天开始从手机优化的案例来逐篇对算法的优化做一个简单的总结专栏。 1. 为什么需要绑核操作? 需求决定一切: 需要程序更快执行完成 需要程序避开频繁的CPU调度 需要屏蔽干扰条件验证算法的性能 通常,我们会把进程绑定到大核簇或者小核簇,或者当个cpu上面,以提高程序执行效率。 2. 如何找到我们需要的CPU核? 通过shell可以看到SOC的CPU信息: cat proc/cpuinf..

tim514的博客 3347

深入解析Android14应用安装权限:从声明到授予的完整适配指南

本文深入解析Android14应用安装权限的适配方法,重点介绍了从权限声明到授予的完整流程。与Android13相比,Android14在权限管理机制上进行了重要调整,特别是通过AppOpsManager实现权限的对象化封装。文章详细讲解了权限声明的基础配置、Framework层适配方案、运行时权限授予方法以及常见问题排查指南,帮助开发者高效完成Android14权限适配。

o9p0q1的博客 696

CPU的亲缘性affinity

本文简单介绍一下CPU亲缘性以及实现方法。

清风 1981

Android Input——输入事件ANR执行(十六)

上一篇文章我们介绍了输入事件 ANR 的触发流程,这里我们再来看一下输入事件 ANR的执行流程。

小旭的专栏 944

100天精通Python(基础篇)——第4天:数据类型全解析_从基础到转换

数据类型全解析_从基础到转换

努力让自己发光,对的人才能迎着光而来 11万+

CPU亲和力--affinity

CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行. 一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中, 设置CPU亲合力的掩码可能会获得更好的性能. 一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,   下面的几个宏分别对这个掩码集进行操作: 1. CPU_ZERO() 清空

train的专栏 5542

南京理工大学计算机预推免面试(双非重点关注)

南京理工大学总体来说对双非学校比较友好,上岸率比较高,而且面试形式是线上,在预推免的过程中,可以作为重点关注的学校,但是一定要注意南理报名截止的时间,部分学校可能保研名额公示的比较晚,对于保研边缘人来说很可能会错过,我的建议是,即使不确定能否拿到保研名额,先查一下截止时间,先在系统上报名!!一旦拿到了offer,就是铁的,保底专硕,而且有很大的技巧性,一定要认真看哈!!!每个人的情况可能都不一样,如果有需要帮忙可以私我~~~

D1379951481的博客 2020

CPU Affinity

为了测试笔记本在CPU高负荷运转的时候,风扇

xlnjulp Stay Hungry, Stay Foolish 904

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【基础】CPU亲和性(affinity)指定线程到某个CPU运行

转载:CPU亲和性(affinity)sched_setaffinity() 和 sched_getaffinity() CPU_SET()与CPU_ZERO() CPU亲和性(affinity)就是进程要在某个给定的CPU上尽量长时间的运行而不被迁移到其他处理器的倾向性。 linux内核进程调度器天生具有软CPU亲和性(affinity)的特性,着意味着进程通常不会在处理器之间频繁迁移。这种...

Yannick Jiang 的专栏 2163

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

CPU AFFINITY

cpu 亲和力就是指linux系统中能够将一个或多个进程绑定到一个或者多个处理器上运行。 一个进程的cpu亲合力掩码决定了该进程将在哪个或者哪几个CPU上运行,在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能。 一个CPU的亲和力掩码用一个cpu_set_t结构来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作: 1、CPU_ZERO()清空一个集合 2、C

tym8865的专栏 1316

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

linux进程、线程与cpu的亲和性(affinity)

最近的工作中对性能的要求比较高,下面简单做一下总结: 一、什么是cpu亲和性(affinity)   CPU的亲和性,就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性;再简单的点的描述就将制定的进程或线程绑定到相应的cpu上;在多核运行的机器上,每个CPU本身自己会有缓存,缓存着进程使用的信息,而进程可能会被OS调度到其他CPU上,如此,CPU cache命中率就低了,当绑定CPU后,程序就会一直在指定的cpu跑,不会由操作系统调度到其他CPU上,性能有一定的提.

quarles123的专栏 1055

CPU亲和性(affinity)sched_setaffinity() 和 sched_getaffinity() CPU_SET()与CPU_ZERO()

CPU亲和性(affinity)就是进程要在某个给定的CPU上尽量长时间的运行而不被迁移到其他处理器的倾向性。 linux内核进程调度器天生具有软CPU亲和性(affinity)的特性,着意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。 Linux内核还包含一些机制,它让开发人员可以编程实现硬CPU亲和性(affinity)。着意味着应...

故事就酒的博客 1万+

线程绑定CPU核-sched_setaffinity

CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行. 一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能. 一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作: ·CPU_ZERO() ...

weixin_30295091的博客 199
上一篇: 深入变量的“案发”现场
下一篇: 你的变量究竟存储在什么地方?
normalnotebook
博客等级 码龄24年 647粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值