AWSのArm Graviton Processorのベンチマーク取ってみた

# はじめに

AWSがArmプロセッサ作ったぞー
https://dev.classmethod.jp/cloud/aws/aws-graviton-processors-and-a1-instance/

いやー、面白い時代になってきましたね。じゃ、ベンチ取ろうか。

借りたのはa4.4xlargeです。
どうせ借りるなら一番でかいのだよね

## ハードウェア情報

### cpuinfo

```
processor       : 0
BogoMIPS        : 166.66
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd08
CPU revision    : 3
```

わぁシンプル。

### meminfo

```
MemTotal:       31890024 kB
MemFree:        30876208 kB
MemAvailable:   31291296 kB
Buffers:           61628 kB
Cached:           613284 kB
SwapCached:            0 kB
Active:           239836 kB
Inactive:         480872 kB
Active(anon):      46500 kB
Inactive(anon):      144 kB
Active(file):     193336 kB
Inactive(file):   480728 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 4 kB
Writeback:             0 kB
AnonPages:         45180 kB
Mapped:            56984 kB
Shmem:               852 kB
Slab:             174456 kB
SReclaimable:      95064 kB
SUnreclaim:        79392 kB
KernelStack:        5328 kB
PageTables:         1496 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    15945012 kB
Committed_AS:     433156 kB
VmallocTotal:   135290290112 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
```

よしよし、32GB。

## ベンチマーク

毎回恒例だなこれも。

### STREAM

```
$ ./stream_cxx.out -s 1000M
-------------------------------------------------------------
STREAM version $Revision : 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array Size = 1048576000 (elements), Offset = 0 (elements)
Memory per array = 8000 MiB (= 7.8125 GiB).
Total Memory required = 24000 MiB (= 23.4375 GiB).
Each kernel will be executed 10 times.
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:           23252.8     0.725219     0.721515     0.727269
Scale:          23402.8     0.719412     0.716889     0.722033
Add:            25384.3     0.992476     0.991392     0.994607
Triad:          25395.3     0.993181     0.990963     0.995537
-------------------------------------------------------------
```

んー、見た感じRyzenと同じ2chだけどこっちのほうがまともに性能出ている気がしてならないｗ

### FFT

```
$ OMP_NUM_THREADS=8 ./fftw
3-D FFT: 128 x 128 x 128
On-board: 0.036567 msec, 6.021927 GFLOPS.
On-board: 0.034567 msec, 6.370299 GFLOPS.
3-D FFT: 256 x 256 x 256
On-board: 0.326622 msec, 6.163900 GFLOPS.
On-board: 0.325252 msec, 6.189869 GFLOPS.
```

```
$ OMP_NUM_THREADS=16 ./fftw
3-D FFT: 128 x 128 x 128
On-board: 0.025472 msec, 8.644864 GFLOPS.
On-board: 0.021570 msec, 10.208861 GFLOPS.
3-D FFT: 256 x 256 x 256
On-board: 0.212703 msec, 9.465130 GFLOPS.
On-board: 0.210533 msec, 9.562730 GFLOPS.
```

Ryzen 1800X < Gravitonな感じ。まぁ帯域ちゃんと出てるからな…

### GEMM

OpenBLASのコンパイルログを見ると

```
cc -O2 -DMAX_STACK_ALLOC=2048 -Wall -DF_INTERFACE_GFORT -fPIC -DNO_LAPACK -DNO_LAPACKE -DSMP_SERVER -DNO_WARMUP -DMAX_CPU_NUMBER=16 -DMAX_PARALLEL_NUMBER=1 -march=armv8-a -mtune=cortex-a72 -DASMNAME=smax -DASMFNAME=smax_ -DNAME=smax_ -DCNAME=smax -DCHAR_NAME=\"smax_\" -DCHAR_CNAME=\"smax\" -DNO_AFFINITY -I.. -I. -UDOUBLE  -UCOMPLEX -c -UUSE_ABS -UUSE_MIN max.c -o smax.o
```

と認識されているので、とみながさんのいう通り、

https://twitter.com/takehiro_t/status/1067350884068159488

A72として認識されている？ようだ。

まぁBLASがあんまり最適ではない、というのはもちろんあるとは思うんだけど、GEMM走らせてみるよー

```
$ OMP_NUM_THREADS=8 ./gemms
M 10240 N 10240 K 10240 al -1 b 1
Dgemm start
memory use 2.34375 GB
17:56:58 initialize done.
48.8027 GFlops, 1.78077e-07
Sgemm start
17:57:45 initialize done.
71.9962 GFlops, 0.00550573
```

```
$ OMP_NUM_THREADS=16 ./gemms
M 10240 N 10240 K 10240 al -1 b 1
Dgemm start
memory use 2.34375 GB
17:54:3 initialize done.
35.4022 GFlops, 2.06921e-07
Sgemm start
17:55:6 initialize done.
68.5788 GFlops, 0
```

さて、ここからどう考えるべきか、というのはなかなか難しい。
ちょっと調べてみたけども、なんかGravitonはクロックとかアーキテクチャとかは全く公開されてなくて(まぁ発表されたばっかだしね) 憶測に憶測を重ねたものになるのはちょっと申し訳のない気持ち。


~~んで、ピーク性能を考えてみると、~~

```
16(Core) * 2(SIMD) * 2(FMA) * 1(Clock?) = 64GFlops/DP
```

~~または~~

```
16(Core) * 2(SIMD) * 2(FMA) * 2(Clock?) = 128GFlops/DP
```

~~とかが妥当そうな気がしてならない。~~

~~と考えると、だいたい効率としては75%/DP, 55%/SPまたは37%/DP, 27%/SP…ってほんとか？~~
~~うーん…謎。ピーク性能をちゃんとみたいものだけど…~~

2018/11/28追記

一部筋から情報を頂いたので、ちょっと考えなおし。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Graviton、CPU implementerが 0x41 (&#39;A&#39;) なのでコアはARMからライセンスしたやつをそのまま使ってるっぽい。CPU partが 0xd08 なのでCortex-A72ですね: <a href="https://t.co/XuIzLkSDZ5">https://t.co/XuIzLkSDZ5</a></p>&mdash; うわの空 (@n_IMRC) <a href="https://twitter.com/n_IMRC/status/1067609008477859840?ref_src=twsrc%5Etfw">2018年11月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

という@n_IMRCさんの分析があるので、GravitonのマイクロアーキテクチャはA72っぽいことがわかる。
(ほんとか？という疑問はあるが)

https://static.docs.arm.com/uan0016/a/cortex_a72_software_optimization_guide_external.pdf

ARMのOptimization Guideによれば、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/59762/353bbf75-8c91-4ed0-a254-86b163381814.png)

だそうなので、FMAは2ポートから出る。

とすると…

```
2(SIMD) * 2(FMA) * 2(port) * x(clock) = 8xFlops
```

というのが1コアあたりの性能となる。
x = 1とすると

```
16(Core) * 8 * 1 = 128GFlops
```

x = 2とすると

```
16(Core) * 8 * 2 = 256GFlops
```

だとするとGEMMの性能がひたすら出ていないことになりそうだが…うーむ。

というか、なんで8スレッドのほうが性能高いのさ…うーむ、ますます意味が分からない。

意味がわからないので、A72の性能を測ってもらった(@tomoaki_teshima さんありがとう！！)

2コアのA72のボードでの結果。
上の結果とは行列の大きさが違うが、これはメモリが足りないため。

```
$ OMP_NUM_THREADS=1 taskset 0x20 ./gemms
M 8192 N 8192 K 8192 al -1 b 1
Dgemm start
memory use 1.5 GB
18:38:25 initialize done.
3.22001 GFlops, 0
Sgemm start
18:44:9 initialize done.
10.1488 GFlops, 0
```

```
$ OMP_NUM_THREADS=2 taskset 0x30 ./gemms
M 8192 N 8192 K 8192 al -1 b 1
Dgemm start
memory use 1.5 GB
18:46:22 initialize done.
6.20409 GFlops, 3.4934e-08
Sgemm start
18:49:21 initialize done.
19.7518 GFlops, 0
```

このボードは、クロックが2GHzなので、ピーク性能は

```
2(Core) * 2(Clock) * 2(SIMD) * 2(FMA) * 2(port) = 32GFlops/DP
```

となる。
とすると、なんかめちゃくちゃ効率が低いことになる。ほんとか？

うーん、これはますますまじめに調査する必要があるのではないか、みたいな気持ちになる。
今度DGEMM自分で書いてみるか…

### HPL

lu2はx86のintrinsicsがもりもり入っているのでちょっとやそっとじゃ動きませんでした。かなしみ。
まぁでもDGEMMのスコアみればだいたいわかろうというもの…

### UnixBench

HPL動かなかったからUnixBenchやるよ！！

```
========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: ip-172-31-4-201: GNU/Linux
   OS: GNU/Linux -- 4.15.0-1028-aws -- #29+nutmeg8-Ubuntu SMP Tue Nov 20 02:59:41 UTC 2018
   Machine: aarch64 (aarch64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   18:33:35 up  1:00,  5 users,  load average: 0.20, 0.37, 0.63; runlevel 2018-11-27

------------------------------------------------------------------------

Benchmark Run: Tue Nov 27 2018 18:33:35 - 18:42:35
16 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       21810037.7 lps   (10.0 s, 2 samples)
Double-Precision Whetstone                     3227.0 MWIPS (9.8 s, 2 samples)
Execl Throughput                               1386.2 lps   (29.6 s, 1 samples)
File Copy 1024 bufsize 2000 maxblocks        222118.0 KBps  (30.0 s, 1 samples)
File Copy 256 bufsize 500 maxblocks           71675.0 KBps  (30.0 s, 1 samples)
File Copy 4096 bufsize 8000 maxblocks        732574.0 KBps  (30.0 s, 1 samples)
Pipe Throughput                              447490.3 lps   (10.0 s, 2 samples)
Pipe-based Context Switching                  44834.2 lps   (10.0 s, 2 samples)
Process Creation                               5272.7 lps   (30.0 s, 1 samples)
Shell Scripts (1 concurrent)                   4976.0 lpm   (60.0 s, 1 samples)
Shell Scripts (8 concurrent)                   2489.7 lpm   (60.0 s, 1 samples)
System Call Overhead                         438755.9 lps   (10.0 s, 2 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   21810037.7   1868.9
Double-Precision Whetstone                       55.0       3227.0    586.7
Execl Throughput                                 43.0       1386.2    322.4
File Copy 1024 bufsize 2000 maxblocks          3960.0     222118.0    560.9
File Copy 256 bufsize 500 maxblocks            1655.0      71675.0    433.1
File Copy 4096 bufsize 8000 maxblocks          5800.0     732574.0   1263.1
Pipe Throughput                               12440.0     447490.3    359.7
Pipe-based Context Switching                   4000.0      44834.2    112.1
Process Creation                                126.0       5272.7    418.5
Shell Scripts (1 concurrent)                     42.4       4976.0   1173.6
Shell Scripts (8 concurrent)                      6.0       2489.7   4149.5
System Call Overhead                          15000.0     438755.9    292.5
                                                                   ========
System Benchmarks Index Score                                         609.1

------------------------------------------------------------------------
Benchmark Run: Tue Nov 27 2018 18:42:35 - 18:51:37
16 CPUs in system; running 16 parallel copies of tests

Dhrystone 2 using register variables      348674166.4 lps   (10.0 s, 2 samples)
Double-Precision Whetstone                    51577.4 MWIPS (9.8 s, 2 samples)
Execl Throughput                              16932.9 lps   (29.5 s, 1 samples)
File Copy 1024 bufsize 2000 maxblocks        450807.0 KBps  (30.0 s, 1 samples)
File Copy 256 bufsize 500 maxblocks          118184.0 KBps  (30.0 s, 1 samples)
File Copy 4096 bufsize 8000 maxblocks       1289904.0 KBps  (30.0 s, 1 samples)
Pipe Throughput                             7147963.2 lps   (10.0 s, 2 samples)
Pipe-based Context Switching                1001199.4 lps   (10.0 s, 2 samples)
Process Creation                              39675.4 lps   (30.0 s, 1 samples)
Shell Scripts (1 concurrent)                  40286.4 lpm   (60.0 s, 1 samples)
Shell Scripts (8 concurrent)                   5567.2 lpm   (60.1 s, 1 samples)
System Call Overhead                        3441956.0 lps   (10.0 s, 2 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  348674166.4  29877.8
Double-Precision Whetstone                       55.0      51577.4   9377.7
Execl Throughput                                 43.0      16932.9   3937.9
File Copy 1024 bufsize 2000 maxblocks          3960.0     450807.0   1138.4
File Copy 256 bufsize 500 maxblocks            1655.0     118184.0    714.1
File Copy 4096 bufsize 8000 maxblocks          5800.0    1289904.0   2224.0
Pipe Throughput                               12440.0    7147963.2   5746.0
Pipe-based Context Switching                   4000.0    1001199.4   2503.0
Process Creation                                126.0      39675.4   3148.8
Shell Scripts (1 concurrent)                     42.4      40286.4   9501.5
Shell Scripts (8 concurrent)                      6.0       5567.2   9278.6
System Call Overhead                          15000.0    3441956.0   2294.6
                                                                   ========
System Benchmarks Index Score                                        4028.6
```

うーむ…

## まとめ

仕様がわからんからよくわからん…
とりあえず、BLASの最適化がまだっぽいのでそれが欲しいなっていうのと、ピーク性能をちゃんと計算したいなっていう…

でも、この調子でArmのプロセッサのインスタンスがたくさん出てきてくれればいいなと思うのであった。
AWSさんをはじめとするクラウド事業者のみなさま、これからも頑張ってください。