tasksetコマンドでLinuxプロセスをCPUコアに固定する方法|affinityマスクの確認とsystemd永続化

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips > tasksetコマンドでLinuxプロセスをCPUコアに固定する方法|affinityマスクの確認とsystemd永続化
「CPUをたくさん積んだのに、特定のプロセスだけが重くなる」「データベースの応答が時々乱れる」——そんな現象に悩んだことはないでしょうか。

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=でサービス再起動後も永続固定できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜ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

「affinity mask: ff」は16進数の0xFF = 2進数の11111111、つまり論理コア0から7の全8コアが対象です。コア固定が一切されていないデフォルト状態を示しています。

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

affinityマスク「30」は16進数の0x30 = 2進数の00110000 = コア4とコア5に対応します。

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の基本操作は理解できます。ただし、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-34,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

PID 1845だけ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 10mpstat -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

この例では論理コア0と4が同じ物理コア(core id: 0)のHTペアです。キャッシュを独占したい場合はペアのどちらか一方だけを指定します(例: -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=を追記
CPUコアの固定は効果が大きいケース(DBサーバー・リアルタイム処理・NUMA環境)がある一方、汎用Webサーバーのように「コアを浮かせた方が効率的」な場合もあります。tasksetを試す際は変更前後でvmstat 1 10mpstat -P ALL 1 5などの性能指標を計測し、改善を確認してから本番適用することをおすすめします。
注意:コア数が少ない環境(2コア以下)でコアを1つに固定すると、CPU使用率が100%に張り付いてシステム全体が応答しなくなる場合があります。固定するコア数はサーバーの総コア数の半数以上を目安にしてください。

CPU affinity設定を理解したら、次はLinuxサーバー全体の性能設計を体系的に学びませんか?

tasksetのような「ピンポイントのチューニング技術」は、カーネルのスケジューラ・メモリ管理・NUMAトポロジーの基礎が分かって初めて正しく使えます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。