简要
绑核正如其名,将线程/进程绑定在一个或多个CPU核心。该技术可以使进程或线程在特定的处理器上运行,而不会被操作系统调度到其他处理器上。这里有两层含义。
- 如果线程被绑定在指定核心上,则只会在该核心上运行,即使其他核心空闲,该进程或线程也不会被调度到那些核心上运行。
- 如果绑核的线程消亡了,则绑定关系消失,该核又可以被OS调度去做别的线程的活。但如果绑核的请求又来了,则OS会视情况迁移当前核上的线程,再次建立绑核关系。
知识补充
核与CPU
下图为CPU架构图(大致)。
一个CPU基本包括ALU(算数逻辑单元)、控制器(时序逻辑、PC等)、寄存器等,其中外存不属于CPU。架构分为冯诺依曼体系和哈佛体系,区别在于指令和数据是否存储在同一地方。
核的含义是运算单元,包含一套寄存器、L1L2缓存。在传统的CPU中,核与CPU是一对一关系,但如今一个CPU中可以包含多个核心,因此如今的核更接近于传统CPU的含义。每个核心可以独立执行指令和任务,每个核心在逻辑上表现为一个独立的CPU,但他们共享同一个物理芯片。核拥有独立资源,如ALU和L1L2缓存,和同一个CPU的其他核心共享L3缓存、总线接口等 因此一个核心只能同一时刻运行一个线程,每隔一段时间就会切换任务。如果是切换为其他进程的线程,会切换CR3。CR3指的是存储着页目录物理地址,CPU需要使用这个地址来查找页表条目,将虚拟地址翻译为物理地址。在上下文切换的时候,OS需要改变CR3寄存器的值来切换不同进程的页表。
超线程指的是在一个核上运行多个线程,比如说8核16线程,指的就是一个核能够跑2个线程。超线程需要保证的是,两个线程同时不冲突地使用核中的资源。比如一条整数运算指令只会用到整数运算单元,此时浮点数运算单元闲置,可以拿给另一个线程使用。但这需要CPU额外增加一些资源来满足。这都解释了为什么操作系统分配资源(CPU核、内存、磁盘IO等)最小单位是进程,线程是CPU调度和分配的基本单位。
绑核的意义
绑核最明显的作用就是减少上下文切换,提高了缓存利用率。
如何绑核参考https://zhuanlan.zhihu.com/p/432940336
在linux系统上使用pthread_setaffinity_np即可设置线程亲和性
#define _GNU_SOURCE
#include <pthread.h>
#include <sched.h>
void set_thread_affinity(int core_id) {
cpu_set_t cpuset;
pthread_t current_thread = pthread_self();
CPU_ZERO(&cpuset); // 清空CPU集合
CPU_SET(core_id, &cpuset); // 添加一个CPU到集合中
int result = pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset);
if (result != 0) {
// Handle error
}
}
参考
https://zhuanlan.zhihu.com/p/490318618
https://zhuanlan.zhihu.com/p/439381000