UnitV2でncnnをクロスコンパイルしてbenckmarkを実行する手順

## 目的

PC(Ubuntu)にクロスコンパイル環境を構築して、ディープラーニングフレームワークのncnnとベンチマークソフトウェアのbenchmarkビルドし、UnitV2でncnn benchmarkを実行します。

https://github.com/nnn112358/ncnn_benchmark_test

また、こちらのリポジトリで、これまでにCoreMP135、Raspberry Pi Zero 2 W、M5Stack_UnitV2、LicheeNano RV、Luckfox Pico Maxでのncnn benchmarkを比較した結果を公開しています。



## PC環境
まず以下のバージョンのUbuntuをインストールしたPC環境で、クロスコンパイル環境を構築します。

```
Ubuntu 22.04.3 LTS(x64)
```

## コンパイルにライブラリのインストール

 コンパイルに必要なライブラリを含むパッケージをaptからインストールします
 
```
$ sudo apt install crossbuild-essential-armhf crossbuild-essential-arm64
```



## クロスコンパイラのインストール

まず、/opt/ディレクトリの下に「external」フォルダを作成して移動します。

```
$ sudo mkdir /opt/external
$ sudo chmod 777 /opt/external
$ cd /opt/external
```

### クロスコンパイラのダウンロード
UnitV2に対応しているCortex-Aファミリ用GNUツールチェインは以下のファイルとなります。これをARM社のホームページからダウンロードします。
「gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz」

ここでは、curlでツールチェインをダウンロードします。curlがインストールされてなければ、ブラウザからアクセスしてファイルをダウンロードします。

```
$ curl -LO https://developer.arm.com/-/media/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz
```

### クロスコンパイラのインストール

ダウンロードした圧縮ファイルを解凍します。

```
$ tar Jxfv gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf.tar.xz
```

### クロスコンパイラへのパスを通す
環境変数を編集して、binフォルダの下にあるクロスコンパイラの本体「arm-none-linux-gnueabihf-g++」、「arm-none-linux-gnueabihf-gcc」へのパスを通します。

```
$ gedit ~/.bashrc
```

.bashrcの末尾へ、以下のコマンドを追加します。異なるフォルダにインストールする場合にはご使用の環境に合わせて編集してください。

```.bashrc
export PATH="$PATH:/opt/external/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin/"
```

以下のコマンドを実行して、コンパイラのバージョン情報が出れくれば、ツールチェインのインストールが完了です。


以下のコマンドを実行して、コンパイラのバージョン情報が出てれくれば、ツールチェインのインストールが完了です。

```
$ arm-none-linux-gnueabihf-g++ --version
arm-none-linux-gnueabihf-g++ (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16)) 10.2.1 20201103
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```


## ncnnのインストール
ncnnは、Tencentが開発しているモバイルプラットフォーム向けに最適化された高性能なニューラルネットワーク推論コンピューティングフレームワークです。

このシェルスクリプトで、ARMプロセッサ向けにncnnライブラリをgitからクローン、ビルド、そしてインストールします。

```
$ git clone https://github.com/Tencent/ncnn.git -b 20240410 --depth 1 
$ cd ncnn/
```

ncnnのunitv2用のビルド設定ファイルを作成します。
```
$ gedit ./toolchains/arm-linux-gnueabihf-unitv2.toolchain.cmake
```

```arm-linux-gnueabihf-unitv2.toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER "arm-none-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "arm-none-linux-gnueabihf-g++")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")
set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")

# cache flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
```

クロスコンパイラを使ってncnnをビルドします。

```
$ cmake -B build/arm_unitv2 -DCMAKE_TOOLCHAIN_FILE=./toolchains/arm-linux-gnueabihf-unitv2.toolchain.cmake -DNCNN_SIMPLEOCV=ON -DCMAKE_BUILD_TYPE=Release -DNCNN_VULKAN=OFF -DNCNN_BUILD_EXAMPLES=OFF .
$ cmake --build build/arm_unitv2 &&  cmake --install build/arm_unitv2 --prefix install/arm_unitv2
```

## ncnn benckmarkのインストール

ncnnディレクトリ内でbenckmarkのファイルを整理し、それをzip圧縮します。

```
$ cd ncnn
$ mkdir install/arm_unitv2/benchmark
$ cp ./build/arm_unitv2/benchmark/benchncnn ./install/arm_unitv2/benchmark
$ cp ./benchmark/*.param ./install/arm_unitv2/benchmark
$ zip -r ./install/arm_unitv2/arm_unitv2_ncnn_benchmark.zip ./install/arm_unitv2/benchmark

```

## unitv2でのベンチマークの実行

zipファイルをunitv2にscpでコピー、unitv2でncnn benchmarkを実行します。


```
unitv2% unzip arm_unitv2_ncnn_benchmark.zip 
unitv2% cd benchmark
unitv2% ./benchncnn 4 2 0 -1 1
loop_count = 4
num_threads = 2
powersave = 0
gpu_device = -1
cooling_down = 1
          squeezenet  min =  207.65  max =  208.47  avg =  208.12
     squeezenet_int8  min =  149.00  max =  149.16  avg =  149.10
           mobilenet  min =  348.22  max =  351.24  avg =  349.23
      mobilenet_int8  min =  182.69  max =  182.96  avg =  182.88
        mobilenet_v2  min =  254.54  max =  270.19  avg =  258.93
        mobilenet_v3  min =  203.12  max =  203.81  avg =  203.37
          shufflenet  min =  136.41  max =  136.70  avg =  136.56
       shufflenet_v2  min =  126.79  max =  152.76  avg =  133.42
             mnasnet  min =  242.26  max =  243.36  avg =  242.58
     proxylessnasnet  min =  270.56  max =  272.37  avg =  271.54
     efficientnet_b0  min =  388.31  max =  389.73  avg =  388.85
   efficientnetv2_b0  min =  446.40  max =  448.80  avg =  447.12
        regnety_400m  min =  286.05  max =  286.55  avg =  286.31
           blazeface  min =   36.10  max =   36.31  avg =   36.18
           googlenet  min =  655.90  max =  658.45  avg =  656.65
      googlenet_int8  min =  424.22  max =  426.86  avg =  424.95
```

UnitV2でncnnをクロスコンパイルしてbenckmarkを実行することができました。


## 参考資料

https://github.com/nnn112358/ncnn_benchmark_test

https://qiita.com/nnn112358/items/5b978464b005e7209fd8

https://qiita.com/nnn112358/items/5cfc32fd6cd1c8f4fe47

https://qiita.com/nnn112358/items/a4e262efd91641684402

https://qiita.com/nnn112358/items/67847f6779a3deadd5d4

https://qiita.com/nnn112358/items/25f2e08b00d3ca360e97