ARM64用深層学習ライブラリdnnl_aarch64をqemuを使って動かす

#はじめに
ARM64用深層学習ライブラリは、(ARM SVE対応している)Qemu 3.1.0以降を使えば、x86_64上でも動作させることができる。ここでは、インストール手順を記載する。なお、Ubuntu 18.04環境で構築した。本来は、Qemu 3.1.0環境構築手順も必要である。(文末に手順を記載した。しかし、それなしでもSVE命令なしならQemu2.1である程度動く。)

今回構築するのは以下の環境である。(上から順に記載する。)

- ARM64バイナリ(testsやexamplesなど)
- Qemuエミュレータ(3.1以降を推奨)
- ubuntu 18.04 `x86_64`環境




## 環境設定
パッケージを入れる。README.mdに記載している通りの作業である。ARM　SVE命令を利用することを考えると、Qemu 3.1.0を入れたほうが良い。

```bash
docker pull ubuntu:18.04
```

```bash
apt update
apt install git
apt install cmake
```
ARM用のパッケージのインストールは以下である。

```bash
apt install binutils-aarch64-linux-gnu
apt install cpp-8-aarch64-linux-gnu
apt install g++-8-aarch64-linux-gnu
apt install gcc-8-aarch64-linux-gnu
apt install gcc-8-aarch64-linux-gnu-base:amd64
apt install pkg-config-aarch64-linux-gnu
apt install qemu
apt install qemu-block-extra:amd64
apt install qemu-system-arm
apt install qemu-system-common
apt install qemu-system-data
apt install qemu-system-gui
apt install qemu-user
apt install qemu-user-static
apt install qemu-utils
```
次に、dnnl_aarch64/tools/replace.shの記載手順通り行う。

```bash
export CC=/usr/bin/aarch64-linux-gnu-gcc-8
export CXX=/usr/bin/aarch64-linux-gnu-g++-8
export LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib
git clone https://github.com/fujitsu/dnnl_aarch64
cd dnnl_aarch64/mkl-dnn
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
../../tools/replace.sh
make -j28
```

シェアードライブラリパスの修正が必要であるので、以下のリンクコマンドを実行する

```bash
ln -s /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/
```

## プログラム実行
コマンドを実行する。

```bash
cd dnnl_aarch64/mkl-dnn/build/tests/gtests
qemu-aarch64 ./test_reorder
```

実行結果は以下の通りである。(全部で169件のテストなので末端のみを記載する。)

```bash
[----------] 4 tests from TestReorder/reorder_simple_test_s8_s8
[ RUN      ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/0
[       OK ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/0 (212 ms)
[ RUN      ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/1
[       OK ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/1 (216 ms)
[ RUN      ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/2
[       OK ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/2 (486 ms)
[ RUN      ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/3
[       OK ] TestReorder/reorder_simple_test_s8_s8.TestsReorder/3 (491 ms)
[----------] 4 tests from TestReorder/reorder_simple_test_s8_s8 (1405 ms total)

[----------] Global test environment tear-down
[==========] 169 tests from 12 test cases ran. (38438 ms total)
[  PASSED  ] 169 tests.
```

##実行時の環境変数について
環境変数でdnnl_aarch64の設定を変更できる。例えば、以下の変数ではログレベルを設定できる。1以外の設定もあるので、詳細は参考資料を参照のこと

```bash
export MKLDNN_VERBOSE=1
```

- [doc/perf_profile.md](https://github.com/fujitsu/dnnl_aarch64/blob/release_base_0.19/mkl-dnn/doc/perf_profile.md)
- [cmake/options.cmake](https://github.com/fujitsu/dnnl_aarch64/blob/release_base_0.19/mkl-dnn/cmake/options.cmake)


#注意事項
- JIT対応について
   - dnnl_aarch64には、xbyak_aarch64が同梱されているが、reorder(並べ替え)しかJIT化されていないとある(README.mdより)。
- Qemuについて
   - Ubuntu 18.04環境では、デフォルトパッケージはQemu 2.1なので、そのまま動かすと命令セットが足らずコアダンプするときがある。このため、Qemu 3.1以降の環境を作ったほうが良い。SVE等の命令に対応していないQemuの場合、以下のようなメッセージを出力して止まる

```
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction (core dumped)
```
- クロスコンパイル環境について
   - Ubuntuでは、クロスコンパイル環境がパッケージで提供されている。なお、CentOSでは、クロスコンパイル環境がパッケージで提供されているようには見えなかったので、対応していない。
- コンパイラについて
   - sve命令を生成するには、gcc-8以降かつsveのフラグ`-march\=armv8.2-a+sve`を設定する必要がある。
   - Ubuntu 18.04環境のデフォルトコンパイラは、gcc-7である。SVE命令のバイナリを生成するためには、gcc-8が必須である。
   - CentOS8では、デフォルトコンパイラは、gcc-8でありこの点の考慮は不要である。
- 他環境について
   - Ubuntu 18.04環境で、現在は動かしている。Google Colab環境を試したが、(ARMの)ライブラリの依存関係が解決できず実行できるバイナリが生成できなかった。

#補足
##Qemuのコンパイル
Ubuntu 18.04でのコンパイル手順は、以下の通り
パッケージの設定は以下の通りである。なお、aarch64のクロスコンパイルをするためには、上記のパッケージのインストール後に行う必要がある。

```bash
apt install python3
apt install glib2.0-dev
apt install libpixman-1-dev
```
ビルド手順は以下の通りである。

```bash
mkdir build
cd build
../configure
make
```
以下のようにして実行する。また、実行時に`LD_LIBRARY_PATH`(上記)が適切に設定されている必要がある。

```
./aarch64-linux-user/qemu-aarch64 xxxxx
```

##バイナリ操作ツール
上記Ubuntu 18.04では、クロスコンパイルツールを入れた環境だと、以下のように見ることができる。
なお、[binutilsの版数は、2.30](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/architecture-support)である。

```
/usr/bin/aarch64-linux-gnu-objdump -D xxxx
```

#参考資料
- [DNNL_aarch64 ; Deep Neural Network Library for AArch64](https://github.com/fujitsu/dnnl_aarch64)
- [MKL-DNNで学ぶIntel CPUの最適化手法](https://blog.cybozu.io/entry/2019/04/15/170000)
- [Arm SVE命令セットって美味しいの?](https://qiita.com/aKatsuhiroMihara/items/f4799ae4e6f12743b88e)
- エミュレータ
   - [qemu/qemu releases](https://github.com/qemu/qemu/releases)
      - [ChangeLog/ Qemu](https://wiki.qemu.org/ChangeLog/)
      - [qemu package in Ubuntu](https://launchpad.net/ubuntu/+source/qemu)
- 開発環境について
   - [Setting up for sve development - Linaro HPC Workshop 2018](https://www.slideshare.net/linaroorg/setting-up-for-sve-development-linaro-hpc-workshop-2018)
   - コンパイラについて 
      - [Compiler flags across architectures: -march, -mtune, and -mcpu](https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu) 
          - コンパイラフラグと各チップセットの関係について詳しい。
      - [GCC-8/QEmu-3.1を用いたSVE対応版ELFバイナリ用クロスコンパイル環境構築メモ](https://qiita.com/tkato/items/4f457fbeddb10a8b1f1e)
         -  CentOS7にて、ソースコードから各種ツールをコンパイルしてクロスコンパイル環境を構築できる模様である。多分同じ手順で、CentOS8も構築できると思われる。 
      - [GCC 8 Release Series
Changes, New Features, and Fixes](https://gcc.gnu.org/gcc-8/changes.html) GCC-8からSVE命令に対応している。 
      - [(Ubuntu 18.04)Package: gcc-8-aarch64-linux-gnu](https://packages.ubuntu.com/bionic/devel/gcc-8-aarch64-linux-gnu)