cpu affinity

1 Overview

CPU affinity means that the process runs for a long time on the specified CPU, and try not to migrate to other CPUs.

On a multi-core CPU machine, each CPU has its own cache. If the process is not explicitly bound to the CPU, then it is possible to switch between different CPUs under the scheduling of the operating system, then the cache on the original CPU The data is useless, and the cache on the new CPU does not have the previous data, which causes the cache hit rate to decrease. If the CPU affinity is set, after a process is bound to the CPU, the cache hit rate can be maintained at a high level, thereby improving program performance, which is why the CPU affinity is set. Another advantage is to increase the priority of scheduling a specific process, such as binding a process that requires high real-time performance, on the one hand, it can maintain its real-time performance, on the other hand, it can also prevent it from interfering with other processes.

2. Related commands

The following command can check which CPU a certain process (thread) is running on

[root@localhost build]#  ps -eo pid,args,psr | grep ssh
  827 /usr/sbin/sshd -D             1
11436 sshd: root@pts/1              3
11839 grep --color=auto ssh         2
17761 sshd: root@pts/0              3
[root@localhost build]# pstree -p 827
sshd(827)─┬─sshd(11436)───bash(11441)───pstree(11906)
          └─sshd(17761)───bash(17767)───mysql(23070)
[root@localhost build]# ps -To 'pid,lwp,psr,cmd' -p 17761
  PID   LWP PSR CMD
17761 17761   3 sshd: root@pts/0

 

Hyper-Threading technology (Hyper-Threading) simulates two logical cores (CPU cores) into two physical chips, so that a single processor can use thread-level parallel computing. The commonly referred to as dual-core four-thread/quad-core eight-thread refers to It is a CPU that supports hyper-threading technology. [1] It should be noted that hyper-threading technology improves the performance of the processor through delay hiding. In essence, multiple threads share a processing unit. Therefore, the performance obtained by using hyper-threading technology is not truly parallel. [2]

Associated command, taskset

The following operations can change the CPU corresponding to the process

[root@localhost build]# ps -eo pid,args,psr | grep top
12383 top                           3
12387 grep --color=auto top         0
[root@localhost build]# taskset -cp 2 12383
pid 12383's current affinity list: 0-3
pid 12383's new affinity list: 2
[root@localhost build]# ps -eo pid,args,psr | grep top
12383 top                           2
12415 grep --color=auto top         3

There are two main parameters, see the man manual for more information

 -p, --pid
              操作已存在的PID,而不是加载一个新的程序
 -c, --cpu-list
              声明CPU的亲和力使用数字表示而不是用位掩码表示. 例如 0,5,7,9-11.

 

3. Mask

The following paragraph is taken from the man manual of taskset, mainly about the role of mask in CPU affinity.

In short,

The CPU association is represented by a bit mask, the lowest order bit corresponds to the first logical CPU, and the highest order bit corresponds to the last logical CPU. If an invalid mask is given, an error is returned.

You can also specify a one-to-many relationship with a mask. For example, 0x00000003 is to bind CPU No. 0 and No. 1. .

taskset is used to set or retrieve the CPU affinity of a running process given its PID or to launch a new COMMAND with a given CPU affinity. CPU affinity is a scheduler property that "bonds" a process to a given set of CPUs on the system. The Linux

scheduler will honor the given CPU affinity and the process will not run on any other CPUs. Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practical for performance

reasons. Therefore, forcing a specific CPU affinity is useful only in certain applications.

 

The CPU affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corresponding to the last logical CPU. Not all CPUs may exist on a given system but a mask may specify more CPUs than

are present. A retrieved mask will reflect only the bits that correspond to CPUs physically on the system. If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned. The masks are typically

given in hexadecimal. For example,

 

0x00000001

is processor #0

 

0x00000003

is processors #0 and #1

 

0xFFFFFFFF

is all processors (#0 through #31).

 

When taskset returns, it is guaranteed that the given program has been scheduled to a legal CPU

 

4. Programming Examples

There are mainly two function APIs, one for setting and one for obtaining

  • sched_set_affinity() (used to modify the bit mask)
  • sched_get_affinity() (used to view the current bit mask)

A key data structure

  • task_struct

Macro to modify the mask

void CPU_ZERO (cpu_set_t *set)
这个宏对 CPU 集 set 进行初始化,将其设置为空集。
void CPU_SET (int cpu, cpu_set_t *set)
这个宏将 cpu 加入 CPU 集 set 中。
void CPU_CLR (int cpu, cpu_set_t *set)
这个宏将 cpu 从 CPU 集 set 中删除。
int CPU_ISSET (int cpu, const cpu_set_t *set)
如果 cpu 是 CPU 集 set 的一员,这个宏就返回一个非零值(true),否则就返回零(false)。
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h> /* exit */
#include <unistd.h> /* sysconf */

int main(void) {
    int i, nrcpus;
    cpu_set_t mask;
    unsigned long bitmask = 0;

    // 把0号和1号1CPU加入到mask中
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    CPU_SET(1, &mask);
    // 设置CPU亲和性
    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_setaffinity");
        exit(EXIT_FAILURE);
    }

    // 获取CPU情和性
    CPU_ZERO(&mask);
    if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_getaffinity");
        exit(EXIT_FAILURE);
    }

    // 获取逻辑CPU数量
    nrcpus = sysconf(_SC_NPROCESSORS_CONF);
    for (i = 0; i < nrcpus; i++) {
        if (CPU_ISSET(i, &mask)) {
            bitmask |= (unsigned long)0x01 << i;
            printf("processor #%d is set\n", i);
        }
    }

    printf("bitmask = %#lx\n", bitmask);

    exit(EXIT_SUCCESS);
}

 

outputs

[root@localhost cpu]# gcc affinity.c -o affinity
[root@localhost cpu]# ./affinity 
processor #0 is set
processor #1 is set
bitmask = 0x3

 

5. Usage scenarios

  • Tasks that need to handle a lot of calculations
  • Test tasks for testing complex applications
  • Important, sensitive, real-time tasks

 

reference:

[0] https://zhuanlan.zhihu.com/p/259217757

[1] https://www.cnblogs.com/LubinLew/p/cpu_affinity.html

[2] https://baike.baidu.com/item/%E8%B6%85%E7%BA%BF%E7%A8%8B/86034?fromtitle=%E8%B6%85%E7%BA%BF%E7%A8%8B%E6%8A%80%E6%9C%AF&fromid=276864&fr=aladdin

[3] https://www.ibm.com/developerworks/cn/linux/l-affinity.html

 

Guess you like

Origin blog.csdn.net/niu91/article/details/112601415