Opt Technologies Magazine

オプトテクノロジーズ 公式Webマガジン

インフラにおけるCPUアーキテクチャに対する考察

alt

CPUアーキテクチャの違いによる傾向と性能の検証を行いました。こちらではその検証について紹介していきます。

目次

  • あいさつ
  • はじめに
  • インフラにおけるCPUとは
  • CPUアーキテクチャとコスト、性能について
  • 導入検討
  • まとめ

あいさつ

株式会社オプトにて、宮城県仙台市在住のインフラエンジニアをやっています、岩崎浩昭です。コロナ禍以降フルリモート勤務で業務を行なっています。広告運用系プロダクトやオウンメディアのIaaS/SaaS/PaaSなどを横断的に構築・運用しています。

はじめに

本記事は弊社内で、運用環境のアーキテクチャをx86系からARM系への乗り換えを検討した際の、検証・考察を行なった際の資料になります。昨今のSDGsなど、継続利用可能リソースやエネルギーの効率化を考えた際に、企業のインフラで対応できる施策は何かないかと検討した際に、より効率の良いインフラへ基盤を移したら良いのではないかという考えから、まずは、検証してみることになりました。

インフラにおけるCPUとは

現在、主要なCPUにはARM系、x86系、MIPS系の3つがあります、一番多い系統はx86系、次にARM系、最後にMIPS系があります。

なお、MIPSについては現在、CPUとしては工業系の制御で使われる以外には見かけなくなっています。その他の用途としてはHDD/SDDの制御用基盤にて、記憶装置の組み込み制御用として使われています。

最も多く利用されている、x86系はintel 8086から始まったCPU系列で現在はIntel社、AMD社にて製造、提供されており、多くのデータセンターにて利用されています。

最後に近年、サーバー用途に増えてきたARM系CPUですが、ARM Ltdがライセンスを持ち、そのライセンスを受けて数多くの企業が開発製造を行なっています、低消費電力でもともとはモバイル機器に組み込まれるRISC命令を模したCPUですが、昨今の省エネルギー化の波を受けて、サーバーへの転用が行われています。知名度的には、AmazonのGraviton、GoogleのTensor、AppleのM1、ARMのCortex、などが知られており、これらがサーバー向けに利用されています。

CPUアーキテクチャとコスト、性能について

一言にコストと言っても、製造コスト、運用コスト、性能差などがあります。ここではそれぞれのCPUの特徴をもとに向き、不向きを調べていきます。

1.CPUコストについて

x86系は主にintelとAMDの2社が製造し、サーバー用に使われるCPUでは、下表のような価格になっています

CPU ファミリネーム 価格帯
インテル® Xeon® Platinum Processor 81XX Family 3,100 USD ~ 13,000 USD
インテル® Xeon® Gold Processor 61XX Family 1,700 USD ~ 6,000 USD
インテル® Xeon® Gold Processor 51XX Family 1,200 USD ~ 1,700 USD
インテル® Xeon® Silver Processor 41XX Family 400 USD ~ 1,000 USD
インテル® Xeon® Bronze Processor 32XX Family 220 USD ~ 320 USD
AMD EPYC 7003 シリーズ 900 USD ~ 7,000 USD
AMD EPYC 7002 シリーズ 450 USD ~ 6,950 USD
AMD EPYC 7001 シリーズ 475 USD ~ 4,200 USD

ARM系は現在多く利用されているCPUのベンダーは、Amazon、Ampere、Apple、Broadcom、Googleがありますが、もともと自社向けの組み込みシステム向けなので、CPU単体で外販されているものが少ないです。

CPU ファミリネーム 価格帯
AWS Graviton (Cortex-A72) 外販なし
ARM Cortex A72 50 USD ~ 150 USD
Broadcom BCM2711 (Cortex-A72) 50 USD ~ 200 USD
AWS Graviton2 (Neoverse N1) 外販なし
Ampere Altra (Neoverse N1) 3,200 USD ~ 5,800 USD
AWS Graviton3 (Neoverse V1) 外販なし
Google Tensor (Cortex-A76) 外販なし
Apple M1 (ARMv8.5-A compatible) 外販なし

(引用) Mouser Electronics , phoronix.com

AWS Graviton2 とほぼ同等の性能を提供する、Ampere Altra の価格帯とIntelの同等性能の価格帯(インテル® Xeon® Gold Processor 61XX Family)、AMDの価格帯(AMD EPYC 7002 シリーズ)を比較すると、サーバー用Armプロセッサはそれほど安くはないようです。

2.運用コストについて

運用コストについてはワットパワーを比較すればいいのですが、注意点としては、期待される仕事量に対する、ARMとX86系の電力比較をしてみると、実は消費電力にあまり有意差がないという事実がわかります。

詳しくは、『Power Struggles: Revisiting the RISC vs. CISC Debate on Contemporary ARM and x86 Architecturs』という海外の論文などを参考にしてみると良いです。

では、一体何が、x86系とARMで優れているかというと、待機時間における電力消費はARMは極端に低いということが挙げられます。つまるところ、常時負荷をかけるような用途では、ARMもx86も大差はなく、定期的なバッチ処理や不定期な処理を行う場合にARMは優れているといえます。

また、CPUの特性としては、ARMはRISC系の処理が得意なので、整数演算的な、単純にデータを取り出す、表示する、データを書き込むといった処理に強く、処理時間も短くなる傾向があります。

オンプレミスでは、ARM系CPUのメリットは待機時の消費電力が小さく、稼働時間が短く抑えられれば、運用コストは小さいですが、常時負荷をかける運用の場合は、場合によってはx86の方が良い場合もあります。 例を挙げるのであれば、仮想通貨のマイニングといった常時負荷が100%近くかかる使用法には全く向いていないといえます。

つまり、IoTなどの単純な命令の制御や単純な実行トリガー処理、バッチの起動処理と言った仕事を与える場合、Arm系CPUは真価を発揮するでしょう。

大量のデータをバッチ処理で処理するような使い方には向きません、そう言った用途にARM系CPUを使ってしまうと、時間あたりの仕事率がx86系CPUより極端に低くなってしまいます。

3.コスト比較をしてみます

実際に、コストを比較する対象としてAWS上のインスタンスは同規模帯の以下の2インスタンスを比較することにしました。

インスタンスサイズ コスト リソース 実CPU
m6i.large $0.124/h vCPU 2 MEM 8GB Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
m6g.large $0.099/h vCPU 2 MEM 8GB AWS Graviton2 @ 2.5~2.6GHz

料金表の時点で、年間費用をオンデマンドベースで比較してみます。

インスタンスサイズ コスト
m6i.large 1,086.24 USD/年
m6g.large 867.24 USD/年

約20%ほど、コストが圧縮できています、しかしながら、実際の性能が同じとは限らないため、apache benchと姫野ベンチを流してみようと思います。

4.CPU性能の比較をしてみます

ベンチを回す前に各環境のCPUINFOを確認します。

m6i.large

processor    : 0
vendor_id   : GenuineIntel
cpu family  : 6
model       : 106
model name  : Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
stepping    : 6
microcode   : 0xd000331
cpu MHz     : 3504.347
cache size  : 55296 KB
physical id : 0
siblings    : 2
core id     : 0
cpu cores   : 1
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 27
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves wbnoinvd ida arat avx512vbmi pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid md_clear flush_l1d arch_capabilities
bugs        : spectre_v1 spectre_v2 spec_store_bypass swapgs
bogomips    : 5799.95
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:
processor   : 1
vendor_id   : GenuineIntel
cpu family  : 6
model       : 106
model name  : Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
stepping    : 6
microcode   : 0xd000331
cpu MHz     : 2899.978
cache size  : 55296 KB
physical id : 0
siblings    : 2
core id     : 0
cpu cores   : 1
apicid      : 1
initial apicid  : 1
fpu     : yes
fpu_exception   : yes
cpuid level : 27
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves wbnoinvd ida arat avx512vbmi pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid md_clear flush_l1d arch_capabilities
bugs        : spectre_v1 spectre_v2 spec_store_bypass swapgs
bogomips    : 5799.95
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:
LANG=C sar -m CPU 1
Linux 5.15.0-1004-aws (ip-***********)  05/16/22    _x86_64_    (2 CPU)
05:43:32        CPU       MHz
05:43:33        all   3199.95
05:43:34        all   3199.94
05:43:35        all   3200.06

m6g.large

processor    : 0
BogoMIPS    : 243.75
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part    : 0xd0c
CPU revision    : 1
processor   : 1
BogoMIPS    : 243.75
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part    : 0xd0c
CPU revision    : 1
LANG=C sar -m CPU 1
Linux 5.15.0-1004-aws (ip-***********)  05/16/22    _aarch64_   (2 CPU)
05:51:34        CPU       MHz

Graviton2のCPUは隠蔽されている、と前情報がありましたのでわかってはいましたが、周波数が撮れませんでした。過去のプレス記事などからは、2.5GHzという情報がありましたが、確認はできないようです。

それでは気を取り直して、ベンチマークへ行ってみたいと思います。

ベンチ名 各ベンチのソースなど
apache bench Apache Bench Tutorial
姫野ベンチ 姫野ベンチマーク | 理化学研究所情報システム部

まず、Apache Benchで計測を実施してみます。

同時に1000ユーザが、1ユーザーあたり100リクエストを発行した場合を想定します。 -nには1000 x 100 = 100,000を指定します。同時アクセスは100を想定し、-cには100を指定します。

ちなみにサーバーの性能限界が知りたい場合は、-n/-c を増やしていき、結果のFailed requestsが0ではなくなった場合、そこがそのWEBサーバとしての限界値です。

ab -n 1000000 -c 100 http://localhost/
  • m6iの結果
Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Completed 1000000 requests
Finished 1000000 requests
Server Software:        Apache/2.4.52
Server Hostname:        localhost
Server Port:            80
Document Path:          /
Document Length:        10671 bytes
Concurrency Level:      100
Time taken for tests:   72.750 seconds
Complete requests:      1000000
Failed requests:        0
Total transferred:      10945000000 bytes
HTML transferred:       10671000000 bytes
Requests per second:    13745.62 [#/sec] (mean)
Time per request:       7.275 [ms] (mean)
Time per request:       0.073 [ms] (mean, across all concurrent requests)
Transfer rate:          146919.69 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0      12
Processing:     0    7   6.2      7     572
Waiting:        0    7   5.4      7     537
Total:          0    7   6.2      7     572
Percentage of the requests served within a certain time (ms)
  50%      7
  66%      7
  75%      7
  80%      7
  90%      8
  95%     10
  98%     18
  99%     28
 100%    572 (longest request)
  • m6g の場合
Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Completed 1000000 requests
Finished 1000000 requests
Server Software:        Apache/2.4.52
Server Hostname:        localhost
Server Port:            80
Document Path:          /
Document Length:        10671 bytes
Concurrency Level:      100
Time taken for tests:   112.654 seconds
Complete requests:      1000000
Failed requests:        0
Total transferred:      10945000000 bytes
HTML transferred:       10671000000 bytes
Requests per second:    8876.76 [#/sec] (mean)
Time per request:       11.265 [ms] (mean)
Time per request:       0.113 [ms] (mean, across all concurrent requests)
Transfer rate:          94879.09 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       5
Processing:     0   11   6.5     11     449
Waiting:        0   11   4.9     10     299
Total:          0   11   6.5     11     449
Percentage of the requests served within a certain time (ms)
  50%     11
  66%     11
  75%     12
  80%     12
  90%     13
  95%     15
  98%     21
  99%     31
 100%    449 (longest request)

わかりやすいように比較してみると、性能で、ARMの方が約36%ほど性能が低いように見えます。これは、一般的なミドルウエアの使い方を要求した場合、x86に比べてArmは遅いということになります。

項目 m6iスコア m6gスコア
Requests per second:[#/sec] 13745.62 8876.76
Time per request: [ms] 7.275 11.265
Time per request: [ms] 0.073 0.113
Transfer rate: [Kbytes/sec] 146919.69 94879.09

次に理化学研究所のセンター長の姫野龍太郎氏が非圧縮流体解析コードの性能評価のために開発したCPUベンチの姫野ベンチを流します。こちらも3回ずつ流します

  • m6iの場合
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 6849.564713 time(s): 0.489976 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 367 times
 This will take about one minute.
 Wait for a while
 Loop executed for 367 times
 Gosa : 4.882812e-04
 MFLOPS measured : 7327.934633  cpu : 56.027469
 Score based on Pentium III 600MHz : 89.365056
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 6917.557754 time(s): 0.485160 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 371 times
 This will take about one minute.
 Wait for a while
 Loop executed for 371 times
 Gosa : 4.882812e-04
 MFLOPS measured : 7439.206151  cpu : 55.790961
 Score based on Pentium III 600MHz : 90.722026
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 6850.809105 time(s): 0.489887 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 367 times
 This will take about one minute.
 Wait for a while
 Loop executed for 367 times
 Gosa : 4.882812e-04
 MFLOPS measured : 7408.417242  cpu : 55.418805
 Score based on Pentium III 600MHz : 90.346552
  • m6gの場合
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 1955.726392 time(s): 1.716049 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 104 times
 This will take about one minute.
 Wait for a while
 Loop executed for 104 times
 Gosa : 4.882812e-04
 MFLOPS measured : 2057.369600  cpu : 56.550643
 Score based on Pentium III 600MHz : 25.089873
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 1971.909145 time(s): 1.701966 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 105 times
 This will take about one minute.
 Wait for a while
 Loop executed for 105 times
 Gosa : 4.882812e-04
 MFLOPS measured : 2087.807190  cpu : 56.262035
 Score based on Pentium III 600MHz : 25.461063
mimax = 257 mjmax = 257 mkmax = 513
imax = 256 jmax = 256 kmax =512
 Start rehearsal measurement process.
 Measure the performance in 3 times.
 MFLOPS: 1933.957594 time(s): 1.735365 4.882812e-04
 Now, start the actual measurement process.
 The loop will be excuted in 103 times
 This will take about one minute.
 Wait for a while
 Loop executed for 103 times
 Gosa : 4.882812e-04
 MFLOPS measured : 2049.113085  cpu : 56.232556
 Score based on Pentium III 600MHz : 24.989184

わかりやすいように比較します、大体ですがCPU性能としては、約3.4倍の性能差があるようです。

回数 m6i[MFLOPS] m6g[MFLOPS]
1 7327.934633 2057.369600
2 7439.206151 2087.807190
3 7408.417242 2049.113085

こうやって、実際の性能を比較してみるとわかりますが、何かしらの連続した計算処理を行わせた場合、ARMはIntelに比べて、性能が低いように見えます。前検証のapacheベンチよりも性能がさらに大きく違うように見えます。

導入検討

コストと性能から見えてくる、ARM環境の使い方ですが、一般的なWebサービス、アプリケーションの基盤の代替に使おうとした場合、性能面から見ると、40%程度割増の環境で、ほぼ同等の性能になることがわかりました。

しかし、連続した計算をするような使い方ではなく、他のアプリケーションの実行トリガーを引いたり、低負荷のシステムに対して代替した場合、Arm系CPUの恩恵は大きく得られると思います。

例を挙げるのであれば、AWSのLambdaやEKS、fargateのような環境に対しては大きなコスト削減が見込めますが、通常のAWS EC2やRDSへの適用した場合、求める出力性能を得るためにはよりコストがかかってしまうことがある点に注意が必要です。

また、x86系とArm系はアーキテクチャが異なるので、基本的には、アプリケーションバイナリイメージは別になります。一時期、Universal Binaryと呼ばれる、いわゆるマルチアーキテクチャバイナリと呼ばれるバイナリイメージが出た時期がありましたが、あのバイナリイメージは、1バイナリイメージに別空間でx86とarm、32bitと64bitのバイナリを入れてあるだけで、実際にはアーキテクチャ毎にバイナリが必要です。

インタプリタ型のアプリケーションの場合、クロスプラットフォームのものがありますので、アーキテクチャを気にする必要はないですが、内部でバイナリライブラリを参照するような場合は注意が必要です。

まとめ

インフラにおける、CPUアーキテクチャについて、性能やコストに焦点を当てて書いてきましたが、これらをまとめると、利用する目的と求める対象が、性能なのか、コストなのか、時間なのかによって、適切に選定する必要があることがわかりました。単純に、コストが安いから入れ替える、といった代替計画や導入計画をしてしまうと、思ったほどの成果が得られないばかりか、余計に運用コストが増大してしまうことが考えられます。

皆さんも、アーキテクチャの向き不向きはよく検討してから、環境やサービスを作りましょう。

最後に、Opt Technologies ではエンジニアを募集中です。カジュアル面談も可能ですので、下記リンク先よりお気軽にご応募ください。