インテル® Agilex™ FPGAでoneAPIサンプルコードの性能を確認してみた

# はじめに

こんにちは。

最近、とある事情でこれを数週間預かることになりまして。

https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=115&No=1252#contents

このボード、現時点（2022年5月現在）ではAgilex™デバイスを使ってoneAPIで遊ぶのに一番良いボードと思ってます。値段もそこそこだし、この状況下で在庫もそれなりにありそうだし。

ということで、なかなか性能が良いで評判のAgilex™ FPGAを使って、dpc++実装だとどの程度のFmaxが出るのか主要なリファレンスデザインを使って試してみました。

え、それだとボード要らないじゃんって？いや、ちゃんとボード入手しないとTerasicさんのBSP使用権がないですから…

で、リファレンスデザインは以下のコマンドで生成しましたが、

```
$ oneapi-cli
```

恐らく以下にあるものと同じです。

https://github.com/oneapi-src/oneAPI-samples/tree/master/DirectProgramming/C%2B%2BSYCL_FPGA/ReferenceDesigns

また、コンパイルの仕方は基本的にすべて共通ですので、皆さん同じ結果を得られるはずです。cmakeでboardを指定していることに注意してください。

```
$ mkdir build
$ cd build
$ cmake .. -DFPGA_BOARD=de10_agilex:B2E2_8GBx4
$ make fpga
```

# Fmax評価

いきなりですが、結果は以下のようになりました。Seedは特にいじっていないので、Seedを振ればもっと良い結果になる可能性はあります。
ちなみに、今回使ったボードに載っているAgilex™デバイスはAGF014というタイプで、主要なリソース量は以下になります。

ALM: 487,200
RAM block: 7,110
DSP block: 4,510


| リファレンスデザイン名 | Kernel Fmax | ALM使用数 | M20K使用数 | DSP使用数 |
|:-:|:-:|:-:|:-:|:-:|
| Adaptive Noise Reduction (anr)  | 550.35MHz | 99,946 | 743 | 31 |
| CRR Binomial Tree Model for Option Pricing (crr)  | 502.51MHz | 428,613  | 2,863  | 1,280 |
| Database Query Acceleration (db)  | 531.34MHz  |  245,081 |  1,238 | 120 |
| GZIP Compression (gzip)  | 526.31MHz  | 279,238 | 4,002 | 0 |
| Merge Sort (merge_sort)  | 243.19MHz  | 249,381   | 1,245   | 0 |
| MVDR Beamforming (mvdr_beamforming)  |  406.0MHz  | 166,815  | 1,187  |615  |
| QR Decomposition of Matrices (qrd)  | 525.21MHz  |  239,409 |  2,854   | 2,083 |

もちろんデザインによるんですが、比較的複雑なデザインでもあっさり500MHzを超えてきてますね。さすがAgilex™。特に、crrなんかはALMを９割近く使っているのに、500MHz超えてます。
dpc++でこの結果ということは、HLSだともっと頑張れるかもです。


# リソース使用量によるFmax低下評価

通常FPGAでは、内部リソースの使用率が100%に近づいてくるとFmaxが落ちる傾向があります。
ここでは、簡単にカーネルの複製数を調整できる以下のサンプルを使って、内部リソース使用量が増えていくとFmaxがどう変化するかを見てみます。

https://github.com/oneapi-src/oneAPI-samples/tree/master/DirectProgramming/C%2B%2BSYCL_FPGA/Tutorials/DesignPatterns/compute_units

このサンプルの、以下を増やすとカーネル数が増やせるようです。15行目あたり。

```c++:src/compute_units.cpp
constexpr size_t kEngines = 5;
```

ただし、このままだと256までしか増やせません。std:make_index_sequenceを使ってカーネルを増やしているためで、ここの制限を外してやる必要があります。そのために、CMakeLists.txtを修正します。30行目あたり。

```makefile:src/CMakeLists.txt
set(HARDWARE_COMPILE_FLAGS "-Wall ${WIN_FLAG} -fintelfpga -fbracket-depth=512")
```
上記のように-fbranket-depthオプションをを追加してやればOK。

今回のサンプルでは、カーネル数が372で上限となりました。373個にすると、以下のエラーメッセージで終了します。

```
Error (22191): Fitter requires 48619 LABs to implement the design, but the device contains only 48720 LABs. Fitting has terminated due to high LAB utilization.
```

結果ですが、以下のようになりました。今回もSeedの設定はしていませんので、Defaultの状態になっています。時間があれば、Seedをある程度振ってベストの値でまとめたいところですが…

| Kernel数 | Kernel Fmax | ALM使用数 | M20K使用数 | DSP使用数 |
|:-:|:-:|:-:|:-:|:-:|
| 5  |  537.63MHz  | 83,250  |  551  | 0  |
| 10  |  563.06MHz  | 88,207  |  556  | 0  |
| 50  |  539.33MHz  |  137,657  | 598  |  0 |
| 100  | 539.33MHz  |  193.383  | 651  |  0 |
| 200  | 517.06MHz  | 303,895   | 757  |  0 |
| 250  | 540.54MHz  | 357,003 |  807  | 0  |
| 300  | 492.36MHz  | 408,779  | 858  | 0  |
| 350  | 566.57MHz  | 448,077  | 921  | 0  |
| 370  |  565.61MHz  | 468,624  |  941  | 0  |
| 372  | 490.43MHz  |  469,690   | 943  |  0 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95821/53f07b43-8925-3b1e-ded7-e2f32a51fbe9.png)

さすがAgilex™、使用率が96%を超えてもびくともしないですね。
カーネル300個のところでFmaxが落ちていますが、試しにSeed=2で試したところ539.33MHzという結果が得られました。少なくともカーネル370個付近までは、安定して530MHz以上の結果が得られそうです。Seedを振れば570MHz近辺も余裕そうですね。
372個のところでもFmaxが落ちていますが、ここは10パターンほどSeed振ってもむしろMETすらしない（373個のときと同じ症状）感じでした。さすがにこの辺が容量的には限界のようです。
とはいえ、Agilex™がやはりよく詰まるというのは確かなように見えます。

# まとめ

今回の結果からして、dpc++でカーネルを書いて9割以上ぎゅうぎゅうに回路を詰め込んでも、500MHz以上で動いてくれる可能性が比較的高そうです。
皆さんもぜひ使ってみてください。

それでは。