Linuxのスケジューラ(CFS)はデフォルトで、プロセスを全CPUコアに自由に移動させます。CPU使用率の平準化としては正しい動作ですが、このコア間移動がL1/L2キャッシュのコールドミスを引き起こし、レイテンシに敏感なワークロードで意図しない性能劣化につながることがあります。
この記事では、
tasksetコマンドを使ってプロセスを特定のCPUコアに固定する方法を解説します。affinityマスクの読み方、/proc/PID/statusでの割り当て確認、systemdのCPUAffinity=による永続化設計まで、RHEL 9.4の実機で確認した手順を紹介します。この記事のポイント
・taskset -p PID でプロセスの現在のCPU affinityを確認できる
・taskset -c コア番号 コマンド で起動時からコアを指定して実行できる
・/proc/PID/status のCpus_allowed_listでも確認可能
・systemdのCPUAffinity=でサービス再起動後も永続固定できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜCPUコアを固定するのか
Linuxのスケジューラは、プロセスの実行効率を高めるため、空きコアへの積極的な移動を行います。この仕組みはCPU全体の使用率を平準化する点では優れていますが、次のようなシナリオでは逆効果になります。・DBサーバーのクエリ処理:PostgreSQL/MySQLのスレッドがコアを移動するたびにキャッシュが無効化され、同じデータの再ロードが発生します
・リアルタイム処理:動画エンコード・金融取引など、ジッター(応答時間のばらつき)を最小化したいワークロード
・マルチソケット(NUMA)環境:別NUMAノードのコアにプロセスが移動すると、ローカルメモリ帯域が大幅に低下する
このような場合に、プロセスが動作するCPUコアを明示的に指定する仕組みがCPU affinity(CPU親和性)です。Linuxでは
tasksetコマンドで、実行中・起動時いずれのプロセスにも設定できます。tasksetコマンドの基本的な使い方
tasksetはutil-linuxパッケージに含まれており、RHEL系ディストリビューションではデフォルトでインストール済みです。# インストール確認(RHEL 9 / AlmaLinux 9) $ rpm -q util-linux util-linux-2.37.4-18.el9.x86_64 # Ubuntu/Debian系の場合 $ dpkg -l util-linux | grep '^ii' ii util-linux 2.39.3-9ubuntu2 amd64 miscellaneous system utilities
1. プロセスの現在のCPU affinityを確認する
taskset -p PIDで、実行中プロセスのaffinityマスクを確認します。# PostgreSQLのメインプロセスPIDを確認 $ systemctl status postgresql-15 | grep 'Main PID' Main PID: 1843 (postgres) # CPU affinityを確認(マスク表示) $ taskset -p 1843 pid 1843's current affinity mask: ff # CPU affinityをコアリスト形式で確認(-cオプション) $ taskset -cp 1843 pid 1843's current affinity list: 0-7
2. 実行中プロセスのコアを変更する(-pオプション)
taskset -p -c コアリスト PIDで、動作中のプロセスのaffinityをその場で変更できます。設定にはsudo(root権限)が必要です。# PID 1843をコア4とコア5のみに固定 $ sudo taskset -p -c 4,5 1843 pid 1843's current affinity list: 0-7 pid 1843's new affinity list: 4,5 # 変更後の確認 $ taskset -cp 1843 pid 1843's current affinity list: 4,5 $ taskset -p 1843 pid 1843's current affinity mask: 30
3. コマンド起動時からコアを指定する
既存プロセスへの後付け設定でなく、最初からコアを指定して起動する場合も-cオプションを使います。# コア2だけで実行 $ taskset -c 2 /usr/bin/python3 myscript.py # コア0とコア1で実行 $ taskset -c 0,1 /usr/sbin/nginx -g 'daemon off;' # コア4から7の範囲で実行 $ taskset -c 4-7 /usr/sbin/mysqld --user=mysql
taskset -pでruntime設定したaffinityはサービス再起動・サーバー再起動でリセットされます。永続化はsystemdで行います(後述)。Linuxサーバーの性能設計や障害対応を体系的に学びたい方は、ハンズオンで実機を使うLinux Master Pro Seminarもあわせてご確認ください。
affinityマスクの読み方(16進数とコアの対応)
affinityは内部でビットマスク(整数)として管理されます。taskset -pの出力は16進数のため、どのコアに対応するかを把握する必要があります。・0x1(= 00000001):コア0のみ
・0x3(= 00000011):コア0、コア1
・0xf(= 00001111):コア0 ~ 3
・0xff(= 11111111):コア0 ~ 7(固定なし)
・0x30(= 00110000):コア4とコア5
・0x55(= 01010101):コア0, 2, 4, 6(偶数コア)
計算方法:コア番号nはビット位置n(右端が0)に対応します。コア4とコア5を指定する場合、2^4 + 2^5 = 16 + 32 = 48(10進数)= 0x30(16進数)になります。
現場では16進マスクの計算よりも
-cオプション(0-3、4,5のようなリスト形式)を使う方が誤りが少なくなります。/proc/PID/statusでCPU割り当てを確認する
tasksetコマンド以外に、/proc/PID/statusファイルからもaffinityを確認できます。シェルスクリプトで複数プロセスを一括チェックする場合に便利です。# コア0のみに固定したプロセスを確認 $ cat /proc/5812/status | grep -i cpu Cpus_allowed: 1 Cpus_allowed_list: 0 # コア4,5に固定したPostgreSQL(PID 1843)を確認 $ cat /proc/1843/status | grep -i cpu Cpus_allowed: 00000030 Cpus_allowed_list: 4-5
Cpus_allowed_listが「0-7」(全コア)でなければ、そのプロセスに何らかのaffinity設定が入っています。全PostgreSQLプロセスのaffinity状態を一括確認するスクリプト例:
# PostgreSQL全プロセスのaffinity一括確認 $ for pid in $(pgrep -x postgres); do cpus=$(grep Cpus_allowed_list /proc/$pid/status 2>/dev/null | awk '{print $2}') printf "PID %-6s Cpus_allowed_list: %s " "$pid" "$cpus" done PID 1843 Cpus_allowed_list: 4-5 PID 1844 Cpus_allowed_list: 4-5 PID 1845 Cpus_allowed_list: 0-7
0-7(全コア)になっていれば、そのプロセスはaffinityが設定されていないことがわかります。systemdのCPUAffinity=でサービスを永続固定する設計
taskset -pでruntime設定したaffinityは、サービス再起動・サーバー再起動でリセットされます。永続化するにはsystemdのユニット設定を使います。1. drop-inファイルで設定する(推奨)
パッケージ管理のユニットファイルを直接編集するのではなく、drop-inファイル(override.conf)に追記する方法が安全です。パッケージ更新でユニットが上書きされても設定が保たれます。# systemctl editでdrop-inファイルを開く $ sudo systemctl edit postgresql-15 # エディタが開いたら以下を入力して保存(コア4とコア5に固定) [Service] CPUAffinity=4 5 # drop-inが作成されたことを確認 $ cat /etc/systemd/system/postgresql-15.service.d/override.conf [Service] CPUAffinity=4 5 # daemon-reloadしてから再起動 $ sudo systemctl daemon-reload $ sudo systemctl restart postgresql-15
2. 設定後の確認
# メインPIDを取得して確認 $ main_pid=$(systemctl show postgresql-15 -p MainPID | cut -d= -f2) $ echo "Main PID: $main_pid" Main PID: 1891 $ taskset -cp $main_pid pid 1891's current affinity list: 4-5 # /proc経由でも確認 $ grep Cpus_allowed_list /proc/$main_pid/status Cpus_allowed_list: 4-5
3. CPUAffinity=の書式
・CPUAffinity=4 5:コア4とコア5(スペース区切り)・CPUAffinity=0-3:コア0からコア3(範囲指定)
・CPUAffinity=0 2 4 6:偶数コアのみ(SMT物理コア側を指定する例)
ユニットファイルに直接書く場合は
CPUAffinity=のある行をそのまま追加できます。トラブルシュート
「Operation not permitted」エラーが出る
$ taskset -p -c 4,5 1843 taskset: failed to set pid 1843's affinity: Operation not permitted
・権限不足:他ユーザーのプロセスのaffinityを変更するにはroot権限が必要です。
sudo tasksetで実行してください・cgroupのAllowedCPUs制限:systemdのユニットに
AllowedCPUs=が設定されている場合、tasksetはその範囲内にしか変更できません。systemctl show サービス名 -p AllowedCPUsで確認してください設定したのに再起動後にリセットされる
taskset -pはruntime設定のため、プロセス・サービス・OSの再起動でリセットされます。永続化には前節のsystemdCPUAffinity=(drop-inファイル)を使います。期待通りの性能改善が得られない
・NUMAトポロジーを確認する:マルチソケット環境では、コアだけでなくメモリの局所性(NUMAノード)も重要です。numactl --hardwareでNUMAノードとコアの対応を確認し、同一ノード内のコアに固定してください・Hyper-Threading(SMT)の影響:同一物理コアの2スレッド(例: コア0とコア1)は演算リソースを共有します。真の独占が必要な場合は1スレッドのみ指定するか、SMTを無効化することを検討してください
・固定するコアが少なすぎる:コアを絞りすぎると逆にCPU待ちが増えます。稼働率を
vmstat 1 10やmpstat -P ALL 1 5で確認しながら固定するコア数を調整してくださいコア番号と物理コアの対応を確認する
Hyper-Threadingが有効な場合、物理コアが論理コアのペアになります。/proc/cpuinfoで対応を確認してから設定します。# 論理コアと物理コアの対応を確認 $ grep -E '^processor|^core id|^physical id' /proc/cpuinfo | paste - - - processor : 0 core id : 0 physical id : 0 processor : 1 core id : 1 physical id : 0 processor : 2 core id : 2 physical id : 0 processor : 3 core id : 3 physical id : 0 processor : 4 core id : 0 physical id : 0 processor : 5 core id : 1 physical id : 0 processor : 6 core id : 2 physical id : 0 processor : 7 core id : 3 physical id : 0
-c 0のみ)。逆にキャッシュを共有させたい場合はペア両方を指定します(例: -c 0,4)。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| プロセスのaffinity確認(マスク形式) | taskset -p PID |
| プロセスのaffinity確認(コアリスト形式) | taskset -cp PID |
| 実行中プロセスをコアに固定 | sudo taskset -p -c 4,5 PID |
| 起動時からコアを指定して実行 | taskset -c 0,1 コマンド |
| /proc経由でaffinity確認 | grep Cpus_allowed_list /proc/PID/status |
| systemdサービスへの永続固定 | drop-inにCPUAffinity=を追記 |
tasksetを試す際は変更前後でvmstat 1 10やmpstat -P ALL 1 5などの性能指標を計測し、改善を確認してから本番適用することをおすすめします。注意:コア数が少ない環境(2コア以下)でコアを1つに固定すると、CPU使用率が100%に張り付いてシステム全体が応答しなくなる場合があります。固定するコア数はサーバーの総コア数の半数以上を目安にしてください。
CPU affinity設定を理解したら、次はLinuxサーバー全体の性能設計を体系的に学びませんか?
tasksetのような「ピンポイントのチューニング技術」は、カーネルのスケジューラ・メモリ管理・NUMAトポロジーの基礎が分かって初めて正しく使えます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:udev rulesでLinuxのデバイス名を固定する方法|udevadm infoで属性確認からデバイス接続スクリプトまで
- この記事の属するカテゴリ:Linuxtipsへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます