CPUのパフォーマンス：Latency, Throughput, Uops

# はじめに
CPUの性能には，分かりやすいクロック周波数やコア数，スレッド数以外にも各命令のレイテンシやスループット，μOpsがあります．

たとえ同じクロック数でも，1クロックで発行できる命令の性能が異なるため，実質の性能はクロック周波数だけでは判断できません．
よくあるCPUがリリースされたときの解説記事でIPCｘｘ％改善みたいな内容がありますが，これがそのパフォーマンスに相当しています．

ここでは，それらのパフォーマンスについて説明します．

本稿では，これらのレイテンシ，スループットUopsの3つを記載します．
なおデータは，Intel Intrinsics Guideではなく，下記から参照しています．
（Intel Intrinsics Guideの数値は，その数値を選んだ基準があいまいなため）

* [uops](https://uops.info/)
* [Dr. Agner Fog's site](https://www.agner.org/)
* [AIDA64](http://instlatx64.atw.hu/)

特に，uopsは，全ての命令に対してベンチマークを行った結果をまとめたものであり，非常に有用です．

## Latency, Throughput, Uops

### Latency, Throughput 
AVXプログラミングをするときは，全ての命令の挙動を解説している[Intel Intrinsics Guide](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html)を見ることが多いですが，そこには各アーキテクチャごとのLatencyとThroughputが記載されています（一部不完全ですが）．このレイテンシとスループットは以下の意味です．

* Latency：命令が発行されてから，実際に完了するまでのサイクル数 Cycles Per Instruction (CPI)
* Throughput: 同時に発行できる命令数の逆数，つまり，ある命令でCPUがずっと埋まっていた場合に，その命令が完了するサイクル数

CPU内には，複数の整数・浮動小数点の演算ユニットやデータのロードストアのユニットなど，複数の演算ユニットがあります．
そのため，各演算器でパイプラインを組めば，レイテンシを隠蔽することが可能で命令の待ち時間にも他の命令で埋めることができます．
例えばIntelのSkylakeは8つの演算用のポートを持ち，機能に応じて同時のそのポートを使うため8ポートが同時に実行可能なだけパラレルに動きます．
Skylakeの各ポートについて下記表に示します．
例えば，浮動小数点演算はPort0とPort1で動くため，1サイクルで2倍の計算が同時にできます．
レイテンシは，その演算を実現する回路によって異なるため，ポートの数だけからは分かりません．

| Port  | Operations                                    | Latency |
|:-----:|:---------------------------------------------:|:-------:|
|   0   |  int/vec arithmetic, logic, shift             | 1       |
|   0   |  vector string                                | 3       |
|   0   |  FP add/mul/FMA                               | 4       |
|   0   |  encryption                                   | 4       |
|   0   |  int mul                                      | 5       |
|   0   |  int and FP div, sqrt                         | *       |
|   0   |  branch                                       | 1-2     |
|   1   |  int/vec arithmetic, logic, shift             | 1       |
|   1   |  int mul/bit-scan                             | 3       |
|   1   |  FP add/mul/FMA                               | 4       |
|   1   |  int mul                                      | 5       |
|   5   |  int/vec arithmetic, logic                    | 1       |
|   5   |  permute                                      | 1-3     |
|   5   |  x87 FP add, SADBW                            | 3       |
|   5   |  PCLMUL                                       | 7       |
|   6   |  int arithmetic, logic, shift                 | 1       |
|   6   |  jump/branch                                  | 1-2     |
|   2   |  load/address generation                      |         |
|   3   |  load/address generation                      |         |
|   4   |  store                                        |         |
|   7   |  load and store address generation            |         |

### Uops
Uopまたはμopとは，マイクロオペレーションの略です．
アウトオブオーダーのコアを持つプロセッサでは，複雑な命令をμopに分割することができます．
例えば，Read-Modify命令は、Read-μopとModify-μopに分割されます．
もっと具体的な加算命令であれば，下記命令は，1) addressからのメモリのロードと2)それとの演算の2つのuopが必要です．

```asm
vaddps ymm1 ymm2 address
```

パイプラインのボトルネックにより，クロックサイクルあたりのμop数が制限されている場合には，命令が生成するμopの数が重要になります．


### 実例

下記に，本ドキュメントで示すLatencyとThroughput，Uopsの表を示します．
AVX命令の場合，IntelのCPUは，Sandy BridgeからAlderlakeまで記述しています．
AVX2命令の場合，Sandy BridgeとIvy BridgeにはAVX2命令がないため，省略しています．
AMDのCPUは，Zen，Zen2, Zen3の性能を示します．
Zen+の命令の性能はZenと同一のため省略しています．

Sandy BridgeとIvy Bridgeはダイをシュリンクしただけであるためほとんどの命令で動作が一致します．
代表的な違いは半浮動小数点を扱う回路があるか否か程度です．
また，HaswellとBroadwellも同様にダイのシュリンクした関係であるため，ほとんどの命令で動作が一致します．
代表的な違いは浮動小数点の乗算がBroadwellから高速化していることや，gather命令が高速化していることです．
Skylakeは，長きにわたり第6世代から第10世代(Kaby Lake, Coffe Lake, Cascade Lake)までの多くのCPUが該当します．
Icelakeは，Tigerlake，Rocketlakeと同様の性能を持ちます．
Alderlakeは，出たばかりであり，そのパフォーマンスはAIDA64のベンチマークから抜粋しています．

表：_mm256_add_ps (vaddps) のLatencyとThroughput (CPI)．

| Architecture | Latency | Throughput |Uops|
|--------------|:-------:|:----------:|:--:|
| Alderlake    |    2    |    0.5     |  1 |
| Icelake      |    4    |    0.5     |  1 |
| Skylake      |    4    |    0.5     |  1 |
| Broadwell    |    3    |     1      |  1 |
| Haswell      |    3    |     1      |  1 |
| Ivy Bridge   |    3    |     1      |  1 |
| Sandy Bridge |    3    |     1      |  1 |
| Zen3         |    3    |    0.5     |  1 |
| Zen2         |    3    |    0.5     |  1 |
| Zen          |    3    |     1      |  2 |

表：_mm256_hadd_ps (vhaddps) のLatencyとThroughput (CPI)．

| Architecture | Latency | Throughput |Uops|
|--------------|:-------:|:----------:|:--:|
| Alderlake    |    5    |    1.83    |  - |
| Icelake      |    6    |     2      |  3 |
| Skylake      |    6    |     2      |  3 |
| Broadwell    |    5    |     2      |  3 |
| Haswell      |    5    |     2      |  3 |
| Ivy Bridge   |    5    |     2      |  3 |
| Sandy Bridge |    5    |     2      |  3 |
| Zen3         |   6.5   |     2      |  3 |
| Zen2         |   6.5   |     2      |  3 |
| Zen          |    6    |     3      |  8 |

なお，Uopはマイクロフュージョンにより命令がまとめられることがあります．
例えば，下記加算は，引数に取る値がアドレスか，レジスタかでUops異なります．

```asm
vaddps ymm1 ymm2 address
vaddps ymm1 ymm2 ymm3
```
加算はアドレスのロードと加算をマイクロフュージョン可能なため，通常は加算とロードの2のところ，ヒュージョンされてUopsが1になります．

一方vhaddpsはマイクロフュージョンされないため，1+3=4となります．

```asm
vhaddps ymm1 ymm2 address
```

ただ，全てのケースでマイクロフュージョンするかしないかを記載すると大変なため，特質事項がない限りはマイクロフュージョンしない場合の数値を書きます．
これらの詳細情報が必要な場合は，[uops](https://uops.info/)を参照してください．