18.6. 仮想マシンの CPU パフォーマンスの最適化
vCPU は、ホストマシンの物理 CPU と同様、仮想マシンのパフォーマンスにおいて極めて重要です。したがって、vCPU を最適化すると、仮想マシンのリソース効率に大きな影響を及ぼす可能性があります。vCPU を最適化するには、以下を実行します。
- 仮想マシンに割り当てられているホスト CPU の数を調整します。これは、CLI または Web コンソール を使用して実行できます。
vCPU モデルが、ホストの CPU モデルに調整されていることを確認します。たとえば、仮想マシン testguest1 を、ホストの CPU モデルを使用するように設定するには、次のコマンドを実行します。
# virt-xml testguest1 --edit --cpu host-model
ARM 64 システムでは、
--cpu host-passthrough
を使用します。- カーネルの同一ページマージ (KSM) を管理します。
ホストマシンが Non-Uniform Memory Access (NUMA) を使用する場合は、その仮想マシンに対して NUMA を設定 することもできます。これにより、ホストの CPU およびメモリープロセスが、仮想マシンの CPU およびメモリープロセスにできるだけ近くにマッピングされます。事実上、NUMA チューニングにより、仮想マシンに割り当てられたシステムメモリーへのより効率的なアクセスが可能になります。これにより、vCPU 処理の効果が改善されます。
詳細は、仮想マシンで NUMA の設定 および サンプルの vCPU パフォーマンスチューニングシナリオ を参照してください。
18.6.1. コマンドラインインターフェイスを使用した仮想 CPU の追加と削除
仮想マシンの CPU パフォーマンスを増減するには、仮想マシンに割り当てられた仮想 CPU (vCPU) を追加または削除します。
実行中の仮想マシンで実行する場合、これは vCPU ホットプラグおよびホットアンプラグとも呼ばれます。ただし、RHEL 9 では vCPU のホットアンプラグに対応しておらず、Red Hat ではその使用を強く推奨していません。
前提条件
オプション: ターゲット仮想マシン内の vCPU の現在の状態を表示します。たとえば、仮想マシン testguest 上の vCPU の数を表示するには、以下を実行します。
# virsh vcpucount testguest maximum config 4 maximum live 2 current config 2 current live 1
この出力は、testguest が現在 1 vCPU を使用していることを示し、1 つ以上の vCPU をホットプラグして仮想マシンのパフォーマンスを向上できることを示しています。ただし、再起動後に使用される vCPU の testguest 数は 2 に変更され、2 以上の vCPU のホットプラグが可能になります。
手順
仮想マシンに割り当てることができる vCPU の最大数を調整します。これは、仮想マシンの次回起動時に有効になります。
たとえば、仮想マシン testguest の vCPU の最大数を 8 に増やすには、次のコマンドを実行します。
# virsh setvcpus testguest 8 --maximum --config
最大値は、CPU トポロジー、ホストハードウェア、ハイパーバイザー、およびその他の要素によって制限される可能性があることに注意してください。
仮想マシンに割り当てられている現在の vCPU の数を、前の手順で設定した最大値まで調整します。以下に例を示します。
実行中の仮想マシン testguest にアタッチされている vCPU を 4 に増やすには、以下を実行します。
# virsh setvcpus testguest 4 --live
これにより、仮想マシンの次回の起動まで、仮想マシンのパフォーマンスおよび testguest のホスト負荷のフットプリントが高まります。
testguest 仮想マシンにアタッチされている vCPU の数を永続的に 1 に減らすには、次のコマンドを実行します。
# virsh setvcpus testguest 1 --config
これにより、仮想マシンの次回の起動後に、仮想マシンのパフォーマンスおよび testguest のホスト負荷のフットプリントが低下します。ただし、必要に応じて、仮想マシンに追加の vCPU をホットプラグして、一時的にパフォーマンスを向上させることができます。
検証
仮想マシンの vCPU の現在の状態に変更が反映されていることを確認します。
# virsh vcpucount testguest maximum config 8 maximum live 4 current config 1 current live 4
18.6.2. Web コンソールを使用した仮想 CPU の管理
RHEL 9 Web コンソールを使用して、Web コンソールが接続している仮想マシンが使用する仮想 CPU を確認し、設定できます。
前提条件
RHEL 9 Web コンソールがインストールされている。
手順は、Web コンソールのインストールおよび有効化 を参照してください。
- Web コンソールの仮想マシンプラグインが システムにインストールされている。
手順
RHEL 9 Web コンソールにログインします。
詳細は、Web コンソールへのログイン を参照してください。
新しいページが開き、選択した仮想マシンに関する基本情報を含む Overview セクションと、仮想マシンのグラフィカルインターフェイスにアクセスするための Console セクションが表示されます。
概要ペインで、vCPU の数の横にある
をクリックします。vCPU の詳細ダイアログが表示されます。
選択した仮想マシンの仮想 CPU を設定します。
vCPU 数: 現在使用中の vCPU の数
注記vCPU 数は、vCPU 最大値以下にする必要があります。
- vCPU 最大値 - 仮想マシンに設定できる仮想 CPU の最大数を入力します。この値が vCPU 数 よりも大きい場合には、vCPU を追加で仮想マシンに割り当てることができます。
- ソケット - 仮想マシンに公開するソケットの数を選択します。
- ソケットごとのコア - 仮想マシンに公開する各ソケットのコア数を選択します。
コアあたりのスレッド - 仮想マシンに公開する各コアのスレッド数を選択します。
Sockets、Cores per socket、および Threads per core オプションは、仮想マシンの CPU トポロジーを調整することに注意してください。これは、vCPU のパフォーマンスにメリットがあり、ゲスト OS の特定のソフトウェアの機能に影響を与える可能性があります。デプロイメントで別の設定が必要ない場合は、デフォルト値のままにします。
仮想マシンに仮想 CPU が設定されます。
注記仮想 CPU 設定の変更は、仮想マシンの再起動後にのみ有効になります。
18.6.3. 仮想マシンでの NUMA の設定
以下の方法は、RHEL 9 ホストで、仮想マシンの Non-Uniform Memory Access (NUMA) 設定の設定に使用できます。
前提条件
ホストが NUMA 対応のマシンである。これを確認するには、
virsh nodeinfo
コマンドを使用して、NUMA cell(2)
の行を確認します。# virsh nodeinfo CPU model: x86_64 CPU(s): 48 CPU frequency: 1200 MHz CPU socket(s): 1 Core(s) per socket: 12 Thread(s) per core: 2 NUMA cell(s): 2 Memory size: 67012964 KiB
行の値が 2 以上であると、そのホストは NUMA に対応しています。
手順
使いやすさのため、自動化ユーティリティーとサービスを使用して、仮想マシンの NUMA を設定できます。ただし、手動で NUMA を設定すると、パフォーマンスが大幅に向上する可能性が高くなります。
自動方式
仮想マシンの NUMA ポリシーを
Preferred
に設定します。たとえば、仮想マシン testguest5 に対してこれを行うには、次のコマンドを実行します。# virt-xml testguest5 --edit --vcpus placement=auto # virt-xml testguest5 --edit --numatune mode=preferred
ホストで NUMA の自動負荷分散を有効にします。
# echo 1 > /proc/sys/kernel/numa_balancing
umad
サービスを起動して、メモリーリソースで仮想マシンの CPU を自動的に調整します。# systemctl start numad
手動方式
特定ホストの CPU、またはある範囲の CPU に特定の vCPU スレッドをピニングします。これは、NUMA 以外のホストおよび仮想マシンでも可能で、vCPU のパフォーマンスを向上させる安全な方法として推奨されています。
たとえば、次のコマンドでは、仮想マシン testguest6 の vCPU スレッドの 0 から 5 を、ホストの CPU 1、3、5、7、9、11 にそれぞれピニングします。
# virsh vcpupin testguest6 0 1 # virsh vcpupin testguest6 1 3 # virsh vcpupin testguest6 2 5 # virsh vcpupin testguest6 3 7 # virsh vcpupin testguest6 4 9 # virsh vcpupin testguest6 5 11
その後、これが成功したかどうかを確認できます。
# virsh vcpupin testguest6 VCPU CPU Affinity ---------------------- 0 1 1 3 2 5 3 7 4 9 5 11
vCPU スレッドのピニング後に、指定の仮想マシンに関連付けられた QEMU プロセススレッドを、特定ホスト CPU、またはある範囲の CPU に固定することもできます。たとえば、以下のコマンドは、testguest6 の QEMU プロセススレッドを CPU 13 および 15 にピニングし、これが成功したことを確認します。
# virsh emulatorpin testguest6 13,15 # virsh emulatorpin testguest6 emulator: CPU Affinity ---------------------------------- *: 13,15
これで、特定の仮想マシンに対して割り当てられるホストの NUMA ノードを指定することができます。これにより、仮想マシンの vCPU によるホストメモリーの使用率が向上します。たとえば、次のコマンドでは、ホスト NUMA ノード 3 ~ 5 を使用するように testguest6 を設定し、これが成功したかどうかを確認します。
# virsh numatune testguest6 --nodeset 3-5 # virsh numatune testguest6
最善のパフォーマンス結果を得るためにも、上記の手動によるチューニングメソッドをすべて使用することが推奨されます。
関連情報
- vCPU のパフォーマンスチューニングシナリオ例
-
View the current NUMA configuration of your system using the
numastat
utility
18.6.4. vCPU のパフォーマンスチューニングシナリオ例
最適な vCPU パフォーマンスを得るためにも、たとえば以下のシナリオのように、手動で vcpupin
、emulatorpin
、および numatune
設定をまとめて使用することが推奨されます。
開始シナリオ
ホストには以下のハードウェア仕様があります。
- 2 つの NUMA ノード
- 各ノードにある 3 つの CPU コア
- 各コアにある 2 スレッド
このようなマシンの
virsh nodeinfo
の出力は以下のようになります。# virsh nodeinfo CPU model: x86_64 CPU(s): 12 CPU frequency: 3661 MHz CPU socket(s): 2 Core(s) per socket: 3 Thread(s) per core: 2 NUMA cell(s): 2 Memory size: 31248692 KiB
既存の仮想マシンを変更して、8 つの vCPU を使用できるようにします。これは、1 つの NUMA ノードに収まらないことを意味します。
したがって、各 NUMA ノードに 4 つの vCPU を分散し、vCPU トポロジーをホストトポロジーに可能な限り近づけるようにする必要があります。つまり、指定の物理 CPU のシブリングスレッドとして実行される vCPU は、同じコア上のホストスレッドに固定 (ピニング) される必要があります。詳細は、以下の ソリューション を参照してください。
解決方法
ホストトポロジーに関する情報を取得します。
# virsh capabilities
この出力には、以下のようなセクションが含まれます。
<topology> <cells num="2"> <cell id="0"> <memory unit="KiB">15624346</memory> <pages unit="KiB" size="4">3906086</pages> <pages unit="KiB" size="2048">0</pages> <pages unit="KiB" size="1048576">0</pages> <distances> <sibling id="0" value="10" /> <sibling id="1" value="21" /> </distances> <cpus num="6"> <cpu id="0" socket_id="0" core_id="0" siblings="0,3" /> <cpu id="1" socket_id="0" core_id="1" siblings="1,4" /> <cpu id="2" socket_id="0" core_id="2" siblings="2,5" /> <cpu id="3" socket_id="0" core_id="0" siblings="0,3" /> <cpu id="4" socket_id="0" core_id="1" siblings="1,4" /> <cpu id="5" socket_id="0" core_id="2" siblings="2,5" /> </cpus> </cell> <cell id="1"> <memory unit="KiB">15624346</memory> <pages unit="KiB" size="4">3906086</pages> <pages unit="KiB" size="2048">0</pages> <pages unit="KiB" size="1048576">0</pages> <distances> <sibling id="0" value="21" /> <sibling id="1" value="10" /> </distances> <cpus num="6"> <cpu id="6" socket_id="1" core_id="3" siblings="6,9" /> <cpu id="7" socket_id="1" core_id="4" siblings="7,10" /> <cpu id="8" socket_id="1" core_id="5" siblings="8,11" /> <cpu id="9" socket_id="1" core_id="3" siblings="6,9" /> <cpu id="10" socket_id="1" core_id="4" siblings="7,10" /> <cpu id="11" socket_id="1" core_id="5" siblings="8,11" /> </cpus> </cell> </cells> </topology>
- オプション: 適切なツールとユーティリティー を使用して仮想マシンのパフォーマンスをテストします。
ホストに 1 GiB の Huge Page を設定してマウントします。
注記1 GiB huge page は、ARM 64 ホストなどの一部のアーキテクチャーおよび設定では使用できない場合があります。
ホストのカーネルコマンドラインに次の行を追加します。
default_hugepagesz=1G hugepagesz=1G
/etc/systemd/system/hugetlb-gigantic-pages.service
ファイルを以下の内容で作成します。[Unit] Description=HugeTLB Gigantic Pages Reservation DefaultDependencies=no Before=dev-hugepages.mount ConditionPathExists=/sys/devices/system/node ConditionKernelCommandLine=hugepagesz=1G [Service] Type=oneshot RemainAfterExit=yes ExecStart=/etc/systemd/hugetlb-reserve-pages.sh [Install] WantedBy=sysinit.target
/etc/systemd/hugetlb-reserve-pages.sh
ファイルを以下の内容で作成します。#!/bin/sh nodes_path=/sys/devices/system/node/ if [ ! -d $nodes_path ]; then echo "ERROR: $nodes_path does not exist" exit 1 fi reserve_pages() { echo $1 > $nodes_path/$2/hugepages/hugepages-1048576kB/nr_hugepages } reserve_pages 4 node1 reserve_pages 4 node2
これにより、4 つの 1 GiB の huge page が node1 から予約され、さらに別の 4 つの 1 GiB の huge page が node2 から予約されます。
前の手順で作成したスクリプトを実行ファイルにします。
# chmod +x /etc/systemd/hugetlb-reserve-pages.sh
システムの起動時に Huge Page 予約を有効にします。
# systemctl enable hugetlb-gigantic-pages
virsh edit
コマンドを使用して、最適化する仮想マシンの XML 設定 (この例では super-VM) を編集します。# virsh edit super-vm
次の方法で仮想マシンの XML 設定を調整します。
-
仮想マシンが 8 つの静的 vCPU を使用するように設定します。これを行うには、
<vcpu/>
要素を使用します。 トポロジーでミラーリングする、対応するホスト CPU スレッドに、各 vCPU スレッドをピニングします。これを行うには、
<cputune>
セクションの<vcpupin/>
要素を使用します。上記の
virsh 機能
ユーティリティーで示されているように、ホストの CPU スレッドは、各コアで連続的に順次付けされません。また、vCPU スレッドは、同じ NUMA ノード上のホストのコアの利用可能な最大セットに固定される必要があります。表の図については、以下の トポロジーの例 セクションを参照してください。手順 a と b の XML 設定は次のようになります。
<cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='7'/> <vcpupin vcpu='5' cpuset='10'/> <vcpupin vcpu='6' cpuset='8'/> <vcpupin vcpu='7' cpuset='11'/> <emulatorpin cpuset='6,9'/> </cputune>
1 GiB の Huge Page を使用するように仮想マシンを設定します。
<memoryBacking> <hugepages> <page size='1' unit='GiB'/> </hugepages> </memoryBacking>
ホスト上で対応する NUMA ノードからメモリーを使用するように、仮想マシンの NUMA ノードを設定します。これを行うには、
<numatune/>
セクションの<memnode/>
要素を使用します。<numatune> <memory mode="preferred" nodeset="1"/> <memnode cellid="0" mode="strict" nodeset="0"/> <memnode cellid="1" mode="strict" nodeset="1"/> </numatune>
CPU モードが
host-passthrough
に設定され、CPU がpassthrough
モードでキャッシュを使用していることを確認します。<cpu mode="host-passthrough"> <topology sockets="2" cores="2" threads="2"/> <cache mode="passthrough"/>
ARM 64 システムでは、
<cache mode="passthrough"/>
行を省略します。
-
仮想マシンが 8 つの静的 vCPU を使用するように設定します。これを行うには、
検証
仮想マシンの XML 設定に、以下のようなセクションが含まれていることを確認します。
[...] <memoryBacking> <hugepages> <page size='1' unit='GiB'/> </hugepages> </memoryBacking> <vcpu placement='static'>8</vcpu> <cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='7'/> <vcpupin vcpu='5' cpuset='10'/> <vcpupin vcpu='6' cpuset='8'/> <vcpupin vcpu='7' cpuset='11'/> <emulatorpin cpuset='6,9'/> </cputune> <numatune> <memory mode="preferred" nodeset="1"/> <memnode cellid="0" mode="strict" nodeset="0"/> <memnode cellid="1" mode="strict" nodeset="1"/> </numatune> <cpu mode="host-passthrough"> <topology sockets="2" cores="2" threads="2"/> <cache mode="passthrough"/> <numa> <cell id="0" cpus="0-3" memory="2" unit="GiB"> <distances> <sibling id="0" value="10"/> <sibling id="1" value="21"/> </distances> </cell> <cell id="1" cpus="4-7" memory="2" unit="GiB"> <distances> <sibling id="0" value="21"/> <sibling id="1" value="10"/> </distances> </cell> </numa> </cpu> </domain>
- オプション: 適切なツールとユーティリティー を使用して仮想マシンのパフォーマンスをテストし、仮想マシンの最適化の効果を評価します。
トポロジーの例
以下の表は、ピニングされる必要のある vCPU とホスト CPU 間の接続を示しています。
表18.2 ホストトポロジー CPU スレッド
0
3
1
4
2
5
6
9
7
10
8
11
コア
0
1
2
3
4
5
ソケット
0
1
NUMA ノード
0
1
表18.3 仮想マシントポロジー vCPU スレッド
0
1
2
3
4
5
6
7
コア
0
1
2
3
ソケット
0
1
NUMA ノード
0
1
表18.4 ホストと仮想マシントポロジーの組み合わせ vCPU スレッド
0
1
2
3
4
5
6
7
ホストの CPU スレッド
0
3
1
4
2
5
6
9
7
10
8
11
コア
0
1
2
3
4
5
ソケット
0
1
NUMA ノード
0
1
このシナリオでは、2 つの NUMA ノードと 8 つの vCPU があります。したがって、4 つの vCPU スレッドは各ノードに固定 (ピニング) される必要があります。
また、Red Hat では、ホストシステムの操作のために、各ノードで少なくとも 1 つの CPU スレッドを使用できるようにしておくことを推奨します。
以下の例では、NUMA ノードにはそれぞれ 3 コアで、2 個のホスト CPU スレッドがあるため、ノード 0 のセットは、以下のように変換できます。
<vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='4'/> <vcpupin vcpu='2' cpuset='2'/> <vcpupin vcpu='3' cpuset='5'/>
18.6.5. カーネルの同一ページマージの管理
Kernel Same-Page Merging (KSM) は、仮想マシン (VM) 間で同一のメモリーページを共有することにより、メモリー密度を向上させます。ただし、KSM を有効にすると CPU 使用率が増加し、ワークロードによっては全体的なパフォーマンスに悪影響を与える可能性があります。
要件に応じて、単一のセッションに対して、または永続的に KSM を有効または無効にすることができます。
RHEL 9 以降では、KSM はデフォルトで無効になっています。
前提条件
- ホストシステムへのルートアクセス。
手順
KSM を無効にします。
KSM をセッション 1 回分無効にするには、
systemctl
ユーティリティーを使用してksm
サービスおよびksmtuned
サービスを停止します。# systemctl stop ksm # systemctl stop ksmtuned
KSM を永続的に無効にするには、
systemctl
ユーティリティーを使用してksm
サービスおよびksmtuned
サービスを無効にします。# systemctl disable ksm Removed /etc/systemd/system/multi-user.target.wants/ksm.service. # systemctl disable ksmtuned Removed /etc/systemd/system/multi-user.target.wants/ksmtuned.service.
KSM を無効にする前に仮想マシン間で共有されていたメモリーページは、そのまま共有されます。共有を停止するには、以下のコマンドを使用して、システムの PageKSM
ページをすべて削除します。
# echo 2 > /sys/kernel/mm/ksm/run
KSM ページを匿名ページに置き換えると、khugepaged
カーネルサービスは仮想マシンの物理メモリーに透過的なヒュージページを再ビルドします。
- KSM を有効にします。
KSM を有効にすると、CPU 使用率が増大し、CPU 全体のパフォーマンスに影響を及ぼします。
ksmtuned
サービスをインストールします。# dnf install ksmtuned
サービスを起動します。
単一セッションで KSM を有効にするには、
systemctl
ユーティリティーを使用してksm
およびksmtuned
サービスを開始します。# systemctl start ksm # systemctl start ksmtuned
KSM を永続的に有効にするには、
systemctl
ユーティリティーを使用してksm
サービスおよびksmtuned
サービスを有効にします。# systemctl enable ksm Created symlink /etc/systemd/system/multi-user.target.wants/ksm.service
/usr/lib/systemd/system/ksm.service # systemctl enable ksmtuned Created symlink /etc/systemd/system/multi-user.target.wants/ksmtuned.service /usr/lib/systemd/system/ksmtuned.service