1. 程式人生 > 其它 >cpu親和性

cpu親和性

技術標籤:002-作業系統003-計算機網路008效能調優cpu親和性affinity網路優化

1. 概述

CPU親和性,是指程序在指定的CPU長時間執行,而儘量不向其他CPU遷移。

在多核CPU的機器上,每個CPU都有自己的快取,如果程序不顯式的繫結CPU,那麼有可能在作業系統的排程下,在不同的CPU之間切換,那麼原先CPU上的快取資料就沒什麼用了,新CPU上的快取又沒有之前的資料,這就造成了快取命中率降低。如果設定了CPU親和性,一個程序綁定了CPU之後,那麼快取的命中率就能保持在一個較高的水平,從而提高程式效能,這就是為什麼要設定CPU親和性的原因。另一個好處是提高特定程序排程的優先順序,比如一個對實時性要求高的程序做繫結,一方面可以保持它的實時性,另一方面也避免它去幹擾其他程序。

2. 相關命令

如下命令可以檢視某個程序(執行緒)執行在哪個CPU上

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

超執行緒技術(Hyper-Threading), 把兩個邏輯核心(CPU core)模擬成兩個物理晶片,讓單個處理器都能使用執行緒級平行計算,常說的的雙核四執行緒/四核八執行緒指的就是支援超執行緒技術的CPU.[1] 要注意,超執行緒技術是通過延遲隱藏的方法,提高了處理器的效能,本質上,就是多個執行緒共享一個處理單元。因此,採用超執行緒技術所獲得的效能並不是真正意義上的並行。[2]

關聯命令,taskset

如下操作可以更改程序對應的CPU

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

主要引數有兩個,更多資訊可以檢視man手冊

 -p, --pid
              操作已存在的PID,而不是載入一個新的程式
 -c, --cpu-list
              宣告CPU的親和力使用數字表示而不是用位掩碼錶示. 例如 0,5,7,9-11.

3. 掩碼

下面這一段摘自taskset的man手冊,主要講述CPU親和性中掩碼的作用。

簡而言之就是,

CPU關聯用位掩碼錶示,最低階位對應第一個邏輯CPU,最高階位對應最後一個邏輯CPU。如果給出了一個無效的掩碼,則返回一個錯誤。

用掩碼也可以指定一對多的關係,比如 0x00000003就是繫結0號和1號CPU。.

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. 程式設計例項

主要有兩個函式API,一個設定,一個獲取

  • sched_set_affinity()(用來修改位掩碼)
  • sched_get_affinity()(用來檢視當前的位掩碼)

一個關鍵資料結構

  • task_struct

修改掩碼的巨集

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

[[email protected] cpu]# gcc affinity.c -o affinity
[[email protected] cpu]# ./affinity 
processor #0 is set
processor #1 is set
bitmask = 0x3

5. 使用場景

  • 需要處理大量計算的任務
  • 測試複雜應用的測試任務
  • 重要、敏感、實時性的任務

參考:

[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