---
title: 亲和性与绑核
description: "亲和性（Affinity）是进程要在某个给定的CPU上尽量长时间地运行而不被迁移到其他处理器的倾向性。在多核运行的机器上，每个CPU本身自己会有缓存，缓存着进程使用的信息，而进程可能会被 OS 调度到其他CPU上，CPU Cache命中率就低了，当绑定CPU后，程序就会一直在指定的CPU跑，不会由操作系统调度到其他CPU上。这样能够大大提高CPU Cache的命中率，提高性能。"
url: https://www.hikunpeng.com/document/detail/zh/perftuning/progtuneg/kunpengprogramming_05_0005.html
sourcePath: /source/zh/perftuning/progtuneg/kunpengprogramming_05_0005.html
indexId: acd50a12a32f59c6cd77df7d7c77a40547e1381a5607d377243b862fd6d8141463
---
# 亲和性与绑核

亲和性（Affinity）是进程要在某个给定的CPU上尽量长时间地运行而不被迁移到其他处理器的倾向性。在多核运行的机器上，每个CPU本身自己会有缓存，缓存着进程使用的信息，而进程可能会被 OS 调度到其他CPU上，CPU Cache命中率就低了，当绑定CPU后，程序就会一直在指定的CPU跑，不会由操作系统调度到其他CPU上。这样能够大大提高CPU Cache的命中率，提高性能。

1. 使用Shell命令，把进程运行的任务绑定在NUMA和CPU上。
numactl是Linux提供的一个手工调优命令，可以指定进程在某个NUMA node上运行或者特定的CPU核心上运行。

  a. 绑NUMA：numactl --cpubind=0 --membind=0 java SIMDTest_Compare_Max2
  b. 绑CPU核心：numactl -C 0-19 --membind=0 java SIMDTest_Compare_Max2
  c. 验证绑核是否成功：top命令也可以显示CPU被分配给哪个进程。
2. 在程序代码中通过系统API调用指定。
  利用glibc库中的sched_getaffinity接口，获取应用程序当前的CPU亲和性，而通过sched_setaffinity接口则可以把应用程序绑定到固定的某个或某几个CPU上运行。

  接口定义如下：

```
#include <sched.h>
int sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
void CPU_CLR(int cpu, cpu_set_t *set);
int CPU_ISSET(int cpu, cpu_set_t *set);
void CPU_SET(int cpu, cpu_set_t *set);
void CPU_ZERO(cpu_set_t *set);
```


  绑核实例如下：

```
#include <sched.h>
#include <stdio.h>
// 绑定当前进程到CPU0
cpu_set_t cpu_mask;
CPU_ZERO(&cpu_mask);    // 清空集合，确保所有位为0
CPU_SET(0, &cpu_mask); // 将CPU0设置为可调度
if (sched_setaffinity(0, sizeof(cpu_mask), &cpu_mask) == -1) {
perror("sched_setaffinity failed");
} else {
// 绑定成功
}
```


3. 应用软件绑核。
鲲鹏920系列处理器包含2个Super CPU Cluster（SCCL），每个SCCL包含6~8个CPU Cluster，每个CPU Cluster包含4个CPU Core。例如，在KVM虚拟机环境下对KVM进行CPU绑核时，建议尽量分布到多个CPU Cluster中，可以减少同一个CPU Cluster内多个Core竞争导致L3 Cache出现内存带宽瓶颈问题，从而整体提升虚拟机性能。

  a. 在Linux系统中先查询NUMA节点信息以及拓扑结构。
    1 numactl -H

  b. 在Linux系统中编辑虚拟机xml配置文件，设置CPU绑核尽量分布到多个CPU Cluster上，配置举例如下：

```
<domain type = 'KVM'>
<vcpu placement = 'static' cpuset='0,1,4,5,8,9,12,13'>8</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
<vcpupin vcpu='2' cpuset='4'/>
<vcpupin vcpu='3' cpuset='5'/>
<vcpupin vcpu='4' cpuset='8'/>
<vcpupin vcpu='5' cpuset='9'/>
<vcpupin vcpu='6' cpuset='12'/>
<vcpupin vcpu='7' cpuset='13'/>
</cputune>
</domain>
```


    (0, 1)，(4, 5)，(8, 9)，(12, 13)分别在不同的CPU Cluster上。
