CPUアフィニティ

1。概要

CPUアフィニティとは、プロセスが指定されたCPUで長時間実行され、他のCPUに移行しないようにすることを意味します。

マルチコアCPUマシンでは、各CPUに独自のキャッシュがあります。プロセスがCPUに明示的にバインドされていない場合は、オペレーティングシステムのスケジュールに従って、異なるCPUを切り替えてから、元のCPUのキャッシュを切り替えることができます。データは役に立たず、新しいCPUのキャッシュには以前のデータがないため、キャッシュのヒット率が低下します。CPUアフィニティが設定されている場合、プロセスがCPUにバインドされた後、キャッシュヒット率を高レベルに維持できるため、プログラムのパフォーマンスが向上します。そのため、CPUアフィニティが設定されます。もう1つの利点は、高いリアルタイムパフォーマンスを必要とするプロセスのバインドなど、特定のプロセスのスケジューリングの優先度を上げることです。一方で、リアルタイムパフォーマンスを維持でき、他方で、それを防ぐこともできます。他のプロセスへの干渉から。

2.関連コマンド

次のコマンドは、特定のプロセス(スレッド)が実行されているCPUを確認できます。

[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

 

ハイパースレッディングテクノロジー(ハイパースレッディング)は、2つの論理コア(CPUコア)を2つの物理チップにシミュレートするため、1つのプロセッサでスレッドレベルの並列コンピューティングを使用できます。一般に、デュアルコア4スレッド/クアッドコアと呼ばれます。 8スレッドとは、ハイパースレッディングテクノロジーをサポートするCPUのことです。[1]ハイパースレッディングテクノロジーは、遅延隠蔽によってプロセッサのパフォーマンスを向上させることに注意してください。本質的に、複数のスレッドが処理ユニットを共有します。したがって、ハイパースレッディングテクノロジーを使用して得られるパフォーマンスは、真に並列ではありません。[2]

関連するコマンド、タスクセット

以下の操作により、プロセスに対応するCPUを変更できます。

[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

2つの主要なパラメータがあります。詳細については、マニュアルを参照してください。

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

 

3.マスク

次の段落は、主にCPUアフィニティにおけるマスクの役割について、タスクセットのマニュアルから抜粋したものです。

要するに、

CPUの関連付けはビットマスクで表され、最下位ビットは最初の論理CPUに対応し、最上位ビットは最後の論理CPUに対応します。無効なマスクが指定された場合、エラーが返されます。

マスクとの1対多の関係を指定することもできます。たとえば、0x00000003はCPU No.0とNo.1をバインドします。

タスクセットは、指定されたPIDを指定して実行中のプロセスのCPUアフィニティを設定または取得するため、または指定されたCPUアフィニティを使用して新しいコマンドを起動するために使用されます。CPUアフィニティは、システム上の特定のCPUセットにプロセスを「結合」するスケジューラプロパティです。Linux

スケジューラーは指定されたCPUアフィニティーを尊重し、プロセスは他のCPUでは実行されません。Linuxスケジューラーは、自然なCPUアフィニティーもサポートしていることに注意してください。スケジューラーは、パフォーマンスが実用的である限り、プロセスを同じCPUに保持しようとします。

理由。したがって、特定のCPUアフィニティを強制することは、特定のアプリケーションでのみ役立ちます。

 

CPUアフィニティはビットマスクとして表され、最下位ビットは最初の論理CPUに対応し、最上位ビットは最後の論理CPUに対応します。特定のシステムにすべてのCPUが存在するわけではありませんが、マスクはより多くのCPUを指定する場合があります

存在しています。取得されたマスクは、システム上のCPUに物理的に対応するビットのみを反映します。無効なマスク(つまり、現在のシステムに有効なCPUがないことに対応するマスク)が指定された場合、エラーが返されます。マスクは通常

16進数で指定されます。例えば、

 

0x00000001

プロセッサ#0です

 

0x00000003

プロセッサ#0と#1です

 

0xFFFFFFFF

すべてのプロセッサ(#0から#31)です。

 

タスクセットが戻ると、指定されたプログラムが正当なCPUにスケジュールされていることが保証されます

 

4.プログラミング例

主に2つの関数APIがあり、1つは設定用、もう1つは取得用です。

  • 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);
}

 

出力

[root@localhost cpu]# gcc affinity.c -o affinity
[root@localhost 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

 

おすすめ

転載: blog.csdn.net/niu91/article/details/112601415