GNU/Linux >> Linux の 問題 >  >> Linux

LinuxスケジューラからCPUを保護する方法(そのCPUにスレッドをスケジュールするのを防ぎます)?

答えは、cpuset を使用することです。 python cpuset ユーティリティを使用すると、それらを簡単に構成できます。

基本概念

3 CPU セット

  • root :すべての構成に存在し、すべての CPU を含みます (unshielded )
  • system :システム タスクに使用される cpus を含みます - 実行する必要があるが「重要」ではないもの (unshielded) )
  • user :「重要な」タスクに使用される CPU が含まれています - 「リアルタイム」モードで実行したいタスク (Shielded )

shield コマンドはこれら 3 つの cpuset を管理します。

セットアップ中に、すべての可動タスクをシールドされていない cpuset (system) に移動します。 ) 分解中に、移動可能なすべてのタスクを root に移動します。 cpuset.セットアップ後、サブコマンドを使用してタスクをシールドに移動できます (user ) cpuset に加えて、特別なタスク (カーネルスレッド) を root から移動します systemまで (したがって、user のうち cpuset)。

コマンド:

まず、シールドを作成します。当然、シールドのレイアウトはマシン/タスクに依存します。たとえば、4 コアの非 NUMA マシンがあるとします。3 つのコアをシールド専用にしたいとします。 、重要でないタスクのために 1 つのコアを残す;非 NUMA であるため、メモリ ノード パラメータを指定する必要はなく、カーネル スレッドを root で実行したままにします。 cpuset (つまり、すべての cpu にわたって)

$ cset shield --cpu 1-3

一部のカーネル スレッド (特定の CPU にバインドされていないスレッド) は、system に移動できます。 cpuset. (一般に、特定の CPU にバインドされているカーネル スレッドを移動することはお勧めできません)

$ cset shield --kthread on

では、シールドで実行されているものをリストしてみましょう (user ) または非シールド (system ) cpusets:(-v 詳細な場合、プロセス名がリストされます) (2 番目の -v を追加します) 80 文字以上を表示するには)

$ cset shield --shield -v
$ cset shield --unshield -v -v

シールドを止めたい場合 (ティアダウン)

$ cset shield --reset

では、シールド内で処理を実行してみましょう ('--' に続くコマンド cset ではなく、実行するコマンドに渡されます )

$ cset shield --exec mycommand -- -arg1 -arg2

シールドに移動したい実行中のプロセスが既にある場合 (カンマ区切りのリストまたは範囲を渡すことで複数のプロセスを移動できることに注意してください (ギャップがあっても、範囲内のプロセスはすべて移動されます))

$ cset shield --shield --pid 1234
$ cset shield --shield --pid 1234,1236
$ cset shield --shield --pid 1234,1237,1238-1240

高度な概念

cset set/proc - これらにより、CPU セットをより細かく制御できます

セット

cpuset の作成、調整、名前変更、移動、破棄

コマンド

cpuset を作成し、cpus 1 ~ 3 を使用し、NUMA ノード 1 を使用して「my_cpuset1」と呼びます

$ cset set --cpu=1-3 --mem=1 --set=my_cpuset1

CPU 1 と 3 のみを使用するように「my_cpuset1」を変更

$ cset set --cpu=1,3 --mem=1 --set=my_cpuset1

cpuset を破壊する

$ cset set --destroy --set=my_cpuset1

既存の cpuset の名前を変更

$ cset set --set=my_cpuset1 --newname=your_cpuset1

階層型 CPU セットを作成する

$ cset set --cpu=3 --mem=1 --set=my_cpuset1/my_subset1

既存の cpuset を一覧表示します (レベル 1 の深さ)

$ cset set --list

既存の cpuset とその子を一覧表示

$ cset set --list --set=my_cpuset1

既存のすべての cpuset を一覧表示

$ cset set --list --recurse

手続き

スレッドとプロセスを管理する

コマンド

cpuset で実行中のタスクを一覧表示

$ cset proc --list --set=my_cpuset1 --verbose

cpuset でタスクを実行する

$ cset proc --set=my_cpuset1 --exec myApp -- --arg1 --arg2

タスクの移動

$ cset proc --toset=my_cpuset1 --move --pid 1234
$ cset proc --toset=my_cpuset1 --move --pid 1234,1236
$ cset proc --toset=my_cpuset1 --move --pid 1238-1340

タスクとそのすべての兄弟の移動

$ cset proc --move --toset=my_cpuset1 --pid 1234 --threads

すべてのタスクを 1 つの cpuset から別の cpuset に移動

$ cset proc --move --fromset=my_cpuset1 --toset=system

固定されていないカーネル スレッドを cpuset に移動

$ cset proc --kthread --fromset=root --toset=system

カーネル スレッド (特定の CPU に固定されているものを含む) を cpuset に強制的に移動します (注:これはシステムに悲惨な結果をもたらす可能性があります - 何をしているのかを確認してください)

$ cset proc --kthread --fromset=root --toset=system --force

階層の例

階層型 cpuset を使用して、優先グループを作成できます

<オール>
  • system を作成する 1 cpu (0) の cpuset
  • prio_low を作成する cpuset と 1 cpu (1)
  • prio_met を作成する 2 つの CPU を持つ cpuset (1-2)
  • prio_high を作成する 3 つの CPU を持つ cpuset (1-3)
  • prio_all を作成する 4 つのすべての cpus (0-3) を持つ cpuset (これはルートと同じであることに注意してください。ルートから分離しておくことをお勧めします)
  • 上記を実現するには、prio_all を作成してから、prio_all の下にサブセット prio_high を作成します。

    $ cset set --cpu=0 --set=system
    $ cset set --cpu=0-3 --set=prio_all
    $ cset set --cpu=1-3 --set=/prio_all/prio_high
    $ cset set --cpu=1-2 --set=/prio_all/prio_high/prio_med
    $ cset set --cpu=1 --set=/prio_all/prio_high/prio_med/prio_low
    

    これを行うには他に 2 つの方法が考えられます (ただし、cset ほどエレガントではなく、Redhat からの素晴らしいレベルのサポートはないようです):

    1) PID 1 を含むすべてのタスクセット - 素晴らしく簡単です (しかし、伝えられるところでは - 私自身は問題を見たことがありません - スケジューラーで非効率を引​​き起こす可能性があります)。以下のスクリプト (root として実行する必要があります) は、init (pid 1) を含むすべての実行中のプロセスでタスクセットを実行します。これにより、実行中のすべてのプロセスが 1 つまたは複数の「ジャンク コア」に固定されます。また、init も固定されるため、将来のプロセスも「ジャンク コア」のリストで確実に開始されます。

    #!/bin/bash
    
    if [[ -z $1 ]]; then
      printf "Usage: %s '<csv list of cores to set as junk in double quotes>'", $0
      exit -1;
    fi
    
    for i in `ps -eLfad |awk '{ print $4 } '|grep -v PID | xargs echo `; do 
       taskset -pc $1 $i;
    done
    

    2) isolcpus カーネル パラメータを使用します (https://www.kernel.org/doc/Documentation/kernel-parameters.txt のドキュメントはこちら):

    isolcpus=   [KNL,SMP] Isolate CPUs from the general scheduler.
                Format:
                <cpu number>,...,<cpu number>
                or
                <cpu number>-<cpu number>
                (must be a positive range in ascending order)
                or a mixture
                <cpu number>,...,<cpu number>-<cpu number>
    
            This option can be used to specify one or more CPUs
            to isolate from the general SMP balancing and scheduling
            algorithms. You can move a process onto or off an
            "isolated" CPU via the CPU affinity syscalls or cpuset.
            <cpu number> begins at 0 and the maximum value is
            "number of CPUs in system - 1".
    
            This option is the preferred way to isolate CPUs. The
            alternative -- manually setting the CPU mask of all
            tasks in the system -- can cause problems and
            suboptimal load balancer performance.
    

    私はいくつかのプロジェクトでこれらの 2 つと cset メカニズムを使用しました (ちなみに、露骨な自己宣伝を許してください :-))。特定の x86 プラットフォームを任意のソフトウェア作業負荷に。お客様のサイトでテストしたところ、非常に良い結果 (ピーク レイテンシが 270% 削減) が得られたので、ピニングと CPU の分離を行う価値は十分にあります。


    Linux
    1. 公式MSリポジトリからLinuxにMicrosoftTeamsをインストールする方法

    2. LinuxでターミナルからWebを検索する方法

    3. Linux の flock コマンドを使用して、別のルート プロセスがファイルを削除しないようにするにはどうすればよいですか?

    1. Linuxで特定のファイルを提供するパッケージを見つける方法

    2. コマンドラインから Linux (Ubuntu) を再起動するにはどうすればよいですか?

    3. Linux コマンドラインからフォルダーをコピーするにはどうすればよいですか?

    1. Linux – CPUがLinuxで64ビットオペレーティングシステムをサポートしていることを知る方法は?

    2. `ls`が出力をソートしないようにするにはどうすればよいですか?

    3. CからLinuxでPIDによってプロセスのCPU使用率を計算する方法は?