[AWS ParallelCluster]ハイパースレッディングを無効化してHPCジョブの性能を改善

HPCジョブはIntel ハイパースレッディングを無効化すると、性能が改善することがあります。 AWS ParallelClusterを使ってクラスターを構築している場合、設定ファイルからHTを無効化できます。 HT の効果はワークロードに依存するため、HTの有効・無効を評価の上、最終的な方針を決めてください。
2020.08.10

ハイパースレッディングを無効化して性能改善

ハイパフォーマンスコンピューティング(HPC)では、インテルのハイパースレッディング(HT)を無効化することで性能が改善するケースが多々あります。

インテルが AWS と執筆した HPC ワークロードのパフォーマンスに関するホワイトペーパー([1])でも、HTの無効化が推奨されています。

同ホワイトペーパーで引用されている記事([2])では、HT を無効にすることが効果的なユースケースとして、浮動小数点演算を多用するHPCジョブが挙げられています。

A good example of contention that makes HT Technology slower is an HPC job that relies heavily on floating point calculations. In this case, the two threads in each core share a single floating point unit (FPU) and are often blocked by one another.

AWS ParallelCluster でHTを無効化するには?

AWS ParallelClusterはAWSがサポートする、HPCクラスターの管理ツールです。

AWS ParallelCluster でHTを無効化するには [cluster] セクションに次の設定を追加します。

[cluster]
disable_hyperthreading = true

HTはデフォルトでは有効になっているため、明示的に無効化する必要があります。

どうやって HT を無効化している?

HT の無効化は CPU オプションの最適化で実現されています。

CPU オプションを使うと

  1. (ビジネスニーズ)コアライセンス対応のために EC2/RDS インスタンスの CPU コア数をカスタマイズ
  2. (技術ニーズ)ワークロードの特性から CPU コアあたりのスレッドを1に指定してマルチスレッドを無効化

ができます。

例として、c5.2xlarge の CPUコア数は4で、コアあたりのスレッドは2のため、仮想CPU(vCPU)数は8です。

1 向けにコア数を2、コアあたりのスレッドを1にして vCPUを2にたり、2向けにコア数はデフォルトの4のまま、コアあたりのスレッドを1にすることができます。

HT の無効化は2番目のユースケースに該当します。

AWS ParallelClusterの実装を確認

AWS ParallelClusterの実装を確認します。 cli/pcluster/config/pcluster_config.pyでは、 以下のようになっていました。

# Initialize CpuOptions
disable_hyperthreading = cluster_section.get_param_value("disable_hyperthreading")
master_vcpus = get_instance_vcpus(self.region, master_instance_type)
compute_vcpus = get_instance_vcpus(self.region, compute_instance_type)
master_cpu_options = {"CoreCount": master_vcpus // 2, "ThreadsPerCore": 1} if disable_hyperthreading else {}
compute_cpu_options = {"CoreCount": compute_vcpus // 2, "ThreadsPerCore": 1} if disable_hyperthreading else {}

disable_hyperthreading = true の場合(HTを無効化)、ThreadsPerCoreを2から1にし、vCPUをデフォルトの半分にしています。 また、HTの無効化はマスター・コンピュートの両方に適用しています。

CPUの最適化は起動時にのみ指定可能です。そのため、 EC2起動テンプレートでCPU設定を定義しています。

デフォルトでは8vCPUの c5.2xlarge に対して HT を無効化したクラスターを作成すると、起動テンプレートでは

  • vCPU(CoreCount) : 4
  • コアあたりのスレッド数(ThreadsPerCore) : 1

となっていました。

$ aws ec2 describe-launch-template-versions \
    --launch-template-id lt-1234
...
                "CpuOptions": {
                    "CoreCount": 4,
                    "ThreadsPerCore": 1
                }
...

起動インスタンスの HT が無効化されていることを確認するには?

EC2インスタンスの HT 設定は

  • EC2 インスタンス内
  • EC2 API

から確認可能です。

以下では 4 コア、2 スレッド/コア で 8vCPU の c5.2xlarge を使って確認します。

EC2 インスタンス内から確認

Linux の CPU 情報は lscpu コマンドで確認します。

(デフォルト)HT が 有効の場合

  • ソケット数 : 1
  • ソケットあたりのコア数 : 4
  • コアあたりのスレッド : 2

のため、vCPU は 1 * 4 * 2 = 8 です。

$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              8
On-line CPU(s) list: 0-7
Thread(s) per core:  2
Core(s) per socket:  4
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               85
Model name:          Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz
Stepping:            4
CPU MHz:             3423.943
BogoMIPS:            6000.00
Hypervisor vendor:   KVM
Virtualization type: full
L1d cache:           32K
L1i cache:           32K
L2 cache:            1024K
L3 cache:            25344K
NUMA node0 CPU(s):   0-7

lscpuコマンドに--extended オプションをつけると、CPU、ソケット、コアの対応を確認できます。 例えばコア 0 番には CPU 0 番 と CPU 4 番の2つのCPUが対応づけられていることがわかります。

$ lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE
0   0    0      0    0:0:0:0       yes
1   0    0      1    1:1:1:0       yes
2   0    0      2    2:2:2:0       yes
3   0    0      3    3:3:3:0       yes
4   0    0      0    0:0:0:0       yes
5   0    0      1    1:1:1:0       yes
6   0    0      2    2:2:2:0       yes
7   0    0      3    3:3:3:0       yes

HT が 無効の場合

HT を無効化すると、コア数(4)は先程と同じですが、コアあたりのスレッドが2から1になるため、CPU数も半減(8→4)しています。

$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):           1
...

$ lscpu --extendedの実行結果から、コアとCPUが1:1の関係になっていることがわかります。

$ lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE
0   0    0      0    0:0:0:0       yes
1   0    0      1    1:1:1:0       yes
2   0    0      2    2:2:2:0       yes
3   0    0      3    3:3:3:0       yes

EC2 API から確認

EC2 インスタンスの CPU 最適化設定は EC2::DescribeInstances API で確認します。

(デフォルト)HT が 有効の場合

ThreadsPerCore が 2 です。

$ aws ec2 describe-instances --instance-ids i-123
...
                    "CpuOptions": {
                        "CoreCount": 4,
                        "ThreadsPerCore": 2
                    },

HT が 無効の場合

ThreadsPerCore が 1 です。

$ aws ec2 describe-instances --instance-ids i-123
...
                    "CpuOptions": {
                        "CoreCount": 4,
                        "ThreadsPerCore": 1
                    },
...

まとめ

HPCジョブに対して Intel ハイパースレッディングを無効化すると、性能が改善することがあります。 AWS ParallelClusterを使ってHPCクラスターを構築している場合、設定ファイルでdisable_hyperthreading = trueとすると、HTを無効化できます。

HT のインパクトはワークロードに依存するため、実際のワークロードで評価の上、設定方針を決めてください。

それでは。

参考

  1. AWS & Intel : "Achieving optimal price/performance for your HPC workload"
  2. Disabling Intel Hyper-Threading Technology on Amazon Linux | AWS Compute Blog
  3. CPU オプションの最適化 - Amazon Elastic Compute Cloud
  4. [cluster] section - AWS ParallelCluster
  5. Hyper-Threading may be Killing your Parallel Performance
  6. ハイパースレッディング・テクノロジー - Wikipedia
  7. ハイパースレッディングの並列化への影響 : 渡辺宙志