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 デーモンは必要ありません。
- irqbalance デーモンのステータスを確認します。
systemctl status irqbalance
~]# systemctl status irqbalance irqbalance.service - irqbalance daemon Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled) Active: active (running) …Copy to Clipboard Copied! Toggle word wrap Toggle overflow - irqbalance デーモンが実行中の場合は停止します。
systemctl stop irqbalance
~]# systemctl stop irqbalanceCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 起動時に irqbalance が再起動しないことを確認します。
systemctl disable irqbalance
~]# systemctl disable irqbalanceCopy to Clipboard Copied! Toggle word wrap Toggle overflow
手順2.4 IRQ バランスからの CPU の除外
/etc/sysconfig/irqbalance 設定ファイルには、CPU を IRQ バランスサービスによる考慮から除外できるようにする設定が含まれています。このパラメーターは IRQBALANCE_BANNED_CPUS という名前で、64 ビットの 16 進ビットマスクであり、マスクの各ビットは CPU コアを表します。
たとえば、16 コアシステムを実行している場合、CPU 8 から 15 を IRQ バランシングから削除する場合は、以下を実行します。
- 好みのテキストエディターで
/etc/sysconfig/irqbalanceを開き、IRQBALANCE_BANNED_CPUSというタイトルのファイルのセクションを見つけます。Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 変数
IRQBALANCE_BANNED_CPUSのコメントを解除し、次のように値を設定して、CPU 8 - 15 を除外します。IRQBALANCE_BANNED_CPUS=0000ff00
IRQBALANCE_BANNED_CPUS=0000ff00Copy to Clipboard Copied! Toggle word wrap Toggle overflow - これにより、irqbalance プロセスはビットマスクにビットが設定されている CPU (この場合はビット 8 - 15) を無視するようになります。
- 最大 64 個の CPU コアを持つシステムを実行している場合は、それぞれ 8 桁の 16 進数の数値をコンマで区切ります。
IRQBALANCE_BANNED_CPUS=00000001,0000ff00
IRQBALANCE_BANNED_CPUS=00000001,0000ff00Copy to Clipboard Copied! Toggle word wrap Toggle overflow 上記のマスクは、CPU 8 から 15、および CPU 33 を IRQ バランシングから除外します。
注記
Red Hat Enterprise Linux 7.2 以降、
/etc/sysconfig/irqbalance ファイルで IRQBALANCE_BANNED_CPUS が設定されていない場合、irqbalance ツールは isolcpus= カーネルパラメーターによって分離された CPU コア上の IRQ を自動的に回避します。
手順2.5 個々の IRQ への CPU アフィニティーの手動割り当て
/proc/interruptsファイルを表示して、各デバイスで使用されている IRQ を確認します。cat /proc/interrupts
~]# cat /proc/interruptsCopy to Clipboard Copied! Toggle word wrap Toggle overflow このファイルには IRQ のリストが含まれています。各行には、ISRQ 番号、各 CPU で発生した割り込みの数と、その後に IRQ タイプと説明が表示されます。CPU0 CPU1 0: 26575949 11 IO-APIC-edge timer 1: 14 7 IO-APIC-edge i8042 ...[output truncated]...
CPU0 CPU1 0: 26575949 11 IO-APIC-edge timer 1: 14 7 IO-APIC-edge i8042 ...[output truncated]...Copy to Clipboard Copied! Toggle word wrap Toggle overflow - IRQ を 1 つのプロセッサーでのみ実行するように指示するには、echo コマンドを使用して、CPU マスクを 16 進数として特定の IRQ の
smp_affinityエントリーに書き込みます。この例では、IRQ 番号 142 の割り込みを CPU 0 でのみ実行するよう指示しています。echo 1 > /proc/irq/142/smp_affinity
~]# echo 1 > /proc/irq/142/smp_affinityCopy to Clipboard Copied! Toggle word wrap Toggle overflow - この変更は、割り込みが発生した場合にのみ有効になります。設定をテストするには、ディスクアクティビティーを生成し、
/proc/interruptsファイルの変更を確認します。割り込みが発生したと仮定すると、選択した CPU の割り込み数が増加し、他の CPU の番号が変更されていないことがわかります。
手順2.6 タスクセット ユーティリティーを使用してプロセスを CPU にバインドする
タスクセット ユーティリティーは、タスクのプロセス ID (PID) を使用してアフィニティーを表示または設定したり、選択した CPU アフィニティーを使用してコマンドを起動したりするために使用できます。アフィニティーを設定するには、タスクセットに 10 進数または 16 進数で表現された CPU マスクが必要です。マスクの引数は、コマンドまたは変更される PID に対して有効な CPU コアを指定するビットマスクです。
- 現在実行されていないプロセスのアフィニティーを設定するには、
tasksetを使用して CPU マスクとプロセスを指定します。この例では、my_embedded_processは CPU 3 のみを使用するように指示されています (CPU マスクの 10 進バージョンを使用)。taskset 8 /usr/local/bin/my_embedded_process
~]# taskset 8 /usr/local/bin/my_embedded_processCopy to Clipboard Copied! Toggle word wrap Toggle overflow - ビットマスクで複数の CPU を指定することもできます。この例では、
my_embedded_processはプロセッサー 4、5、6、および 7 (CPU マスクの 16 進バージョンを使用) で実行するように指示されています。taskset 0xF0 /usr/local/bin/my_embedded_process
~]# taskset 0xF0 /usr/local/bin/my_embedded_processCopy to Clipboard Copied! Toggle word wrap Toggle overflow - さらに、変更するプロセスの CPU マスクと PID を指定した -p (--pid) オプションを使用して、すでに実行中のプロセスの CPU アフィニティーを設定することもできます。この例では、PID が 7013 のプロセスは CPU 0 でのみ実行するように指示されています。
taskset -p 1 7013
~]# taskset -p 1 7013Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 最後に、-c パラメーターを使用して、CPU マスクの代わりに CPU リストを指定できます。たとえば、CPU 0、4、および CPU 7 - 11 を使用するには、コマンドラインに -c 0,4,7-11 が含まれます。ほとんどの場合、この呼び出しは便利です。
重要
タスクセット ユーティリティーは非均一メモリーアクセス (NUMA) システムで動作しますが、ユーザーはスレッドを CPU および 最も近い NUMA メモリーノードにバインドすることはできません。このようなシステムでは、taskset は推奨されるツールではなく、代わりに高度な機能を備えた numactl ユーティリティーを使用する必要があります。詳細は、「非均一メモリーアクセス」 を参照してください。
関連する man ページ
詳細は、以下の man ページは本セクションに記載の情報に関連しています。
- chrt(1)
- taskset(1)
- nice(1)
- renice(1)
- Linux スケジューリングスキームの説明の sched_setscheduler(2)。