2.4. 割り込みおよびプロセスバインディング

リアルタイム環境では、さまざまなイベントに応答する際にレイテンシーを最小限に抑える必要があります。理想的には、割り込み (IRQ) およびユーザープロセスを異なる専用の CPU で相互に分離することができます。
通常、割り込みは CPU 間で均等に共有されます。これにより、新しいデータおよび命令キャッシュの書き込みによって割り込み処理が遅延し、CPU で発生する他の処理との競合が発生することがよくあります。この問題を回避するには、時間クリティカルな割り込みとプロセスを CPU (または CPU の範囲) 専用にすることができます。このようにして、この割り込みの処理に必要なコードおよびデータ構造は、プロセッサーデータと命令キャッシュ内に可能な限り高い可能性が高くなります。その後、専用プロセスはできるだけ迅速に実行でき、その他のタイムクリティカルなプロセスはすべて残りの CPU 上で実行されます。これは、関係する速度がメモリーの制限や、境界バス帯域幅で利用可能な場合に特に重要になります。ここでは、メモリーをプロセッサーキャッシュにフェッチする待機時間は、全体的な処理時間と決定論に影響します。
実際には、最適なパフォーマンスはアプリケーションによって異なります。たとえば、同様の機能を実行する複数の異なるオペラのチューニングでは、最適なパフォーマンスチューニングが完全に異なります。1 つ目は、オペレーティングシステムの機能および割り込み処理のために 4 つの CPU のうち 2 つを分離し、残りの 2 つの CPU をアプリケーションの処理用にのみ提供することが最適でした。別の環境では、ネットワーク関連のアプリケーションプロセスを、ネットワークデバイスドライバーの割り込みを処理する CPU にバインドすると、最適な決定論が発生しました。最終的に、チューニングは、さまざまな設定を行い、組織に最適なものを見つけます。

重要

ここで説明するプロセスの多くは、所定の CPU または範囲の CPU マスクを把握する必要があります。CPU マスクは、通常 32 ビットマスクで表されます。また、使用するコマンドに応じて、数字または 16 進数で表現することもできます。たとえば、CPU 0 の CPU マスクは ビットマスクとして 00000000000000000000000000000001、10 進数 として 1、および 16 進数として 0x00000001 となります。CPU 0 と 1 の両方の CPU マスクは、ビットマスクとして 00000000000000000000000000000011、10 進数として 3、16 進数として 0x00000003 となります。

手順2.3 irqbalance デーモンの無効化

このデーモンはデフォルトで有効になっており、割り込みの処理を CPU で定期的に強制します。ただし、リアルタイムのデプロイメントでは、アプリケーションは通常特定の CPU にバインドされるため、irqbalance デーモンは必要ありません。
  1. irqbalance デーモンのステータスを確認します。
    ~]# systemctl status irqbalance
    irqbalance.service - irqbalance daemon
       Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled)
       Active: active (running) …
    
  2. irqbalance デーモンが実行している場合は停止します。
    ~]# systemctl stop irqbalance
  3. システムの起動時に irqbalance が再起動しないことを確認します。
    ~]# systemctl disable irqbalance

手順2.4 IRQ バランスからの CPU の除外

/etc/sysconfig/irqbalance 設定ファイルには、ISRQ balacing サービスによって CPU を考慮から除外できる設定が含まれています。このパラメーターには IRQBALANCE_BANNED_CPUS という名前が付けられ、64 ビットの 16 進数ビットマスクです。マスクの各ビットは CPU コアを表します。
たとえば、16 コアシステムを実行している場合、CPU 8 から 15 を IRQ バランシングから削除する場合は、以下を実行します。
  1. 希望するテキストエディターで /etc/sysconfig/irqbalance を開き、IRQBALANCE_BANNED_CPUS というタイトルが付いたファイルのセクションを見つけます。
    # IRQBALANCE_BANNED_CPUS
    # 64 bit bitmask which allows you to indicate which cpu's should
    # be skipped when reblancing irqs. Cpu numbers which have their
    # corresponding bits set to one in this mask will not have any
    # irq's assigned to them on rebalance
    #
    #IRQBALANCE_BANNED_CPUS=
    
  2. この方法で変数 IRQBALANCE_BANNED_CPUS のコメントを解除し、その値を設定して CPU 8 から 15 を除外します。
    IRQBALANCE_BANNED_CPUS=0000ff00
    
  3. これにより、irqbalance プロセスはビットマスクでビットが設定された CPU を無視します。この場合、ビットは 8 ~ 15 になります。
  4. 最大 64 個の CPU コアを持つシステムを実行している場合は、それぞれ 8 桁の 16 進数の数値をコンマで区切ります。
    IRQBALANCE_BANNED_CPUS=00000001,0000ff00
    
    上記のマスクは、CPU 8 から 15、および CPU 33 を IRQ バランシングから除外します。

注記

RedHat EnterpriseLinux 7.2 では、この irqbalance ツールは、IRQBALANCE_BANNED_CPUS/etc/sysconfig/irqbalance ファイルに設定されていない場合に isolcpus= カーネルパラメーターを介して分離された CPU コア上の IRQ を自動的に回避します。

手順2.5 個々の IRQ への CPU アフィニティーの手動割り当て

  1. /proc/interrupts ファイルを参照して、各デバイスが使用している IRQ を確認します。
    ~]# cat /proc/interrupts
    このファイルには IRQ の一覧が含まれています。各行には、ISRQ 番号、各 CPU で発生した割り込みの数と、その後に IRQ タイプと説明が表示されます。
             CPU0       CPU1
    0:   26575949         11         IO-APIC-edge  timer
    1:         14          7         IO-APIC-edge  i8042
    ...[output truncated]...
    
  2. IRQ が 1 つのプロセッサーでのみ実行されるように指示するには、echo コマンドを使用して CPU マスク(16 進数)を特定の IRQ の smp_affinity エントリーに書き込みます。この例では、IRQ 番号 142 の割り込みを CPU 0 でのみ実行するよう指示しています。
    ~]# echo 1 > /proc/irq/142/smp_affinity
  3. この変更は、割り込みが発生した場合にのみ有効になります。設定をテストするには、ディスクアクティビティーを生成し、/proc/interrupts ファイルを変更して変更を確認します。割り込みが発生したと仮定すると、選択した CPU の割り込み数が増加し、他の CPU の番号が変更されていないことがわかります。

手順2.6 taskset ユーティリティーを使用してプロセスの CPU にバインド

この taskset ユーティリティーは、タスクのプロセス ID (PID) を使用してアフィニティーを表示または設定します。または、選択した CPU アフィニティーでコマンドを起動するために使用できます。アフィニティーを設定するには taskset は、CPU マスクを 10 進数または 16 進数で表記する必要があります。マスクの引数は、コマンドまたは変更される PID に対してどの CPU コアが有効なかを指定するビットマスクです。
  1. 現在実行していないプロセスのアフィニティーを設定するには、taskset を使用して CPU マスクとプロセスを指定します。こので例は、my_embedded_process は、CPU 3 のみを使用するように指示されています (CPU マスクの 10 進数バージョンを使用)。
    ~]# taskset 8 /usr/local/bin/my_embedded_process
  2. ビットマスクで複数の CPU を指定することもできます。この例では、my_embedded_process は、プロセッサー 4、5、6、および 7 で実行するように指示されています (CPU マスクの 16 進数バージョンを使用)。
    ~]# taskset 0xF0 /usr/local/bin/my_embedded_process
  3. さらに、-p (--pid) オプションと CPU マスクと、変更するプロセスの PID を使用して、すでに実行しているプロセスの CPU アフィニティーを設定できます。この例では、PID が 7013 のプロセスは CPU 0 でのみ実行されるように指示されています。
    ~]# taskset -p 1 7013
  4. 最後に、-c パラメーターを使用して、CPU マスクの代わりに CPU リストを指定できます。たとえば、CPU 0、4、CPU 7、および CPU 7 から 11 を使用するには、コマンドラインに -c 0,4,7-11 が含まれます。ほとんどの場合、この呼び出しは便利です。

重要

この taskset ユーティリティーは NUMA(Non-Uniform Memory Access) システムで機能しますが、ユーザーが CPU 最も近い NUMA メモリーノードにスレッドをバインドすることはできません。このようなシステムでは、taskset は推奨されるツールではなく、numactl ユーティリティーをその高度な機能に使用する必要があります。詳細は、「非非統合メモリーアクセス」 を参照してください。
関連する man ページ

詳細は、以下の man ページは本セクションに記載の情報に関連しています。

  • chrt(1)
  • taskset(1)
  • nice(1)
  • renice(1)
  • Linux スケジューリングスキームの説明の sched_setscheduler(2)。