OpenCVをMIPSで走らせてみた

# はじめに
これは、OpenCV Advent Calendar 2016 2日目の記事です。関連記事は[目次](http://qiita.com/advent-calendar/2016/opencv)にまとめられています。

# 世界の果てまで~~itteQ~~ OpenCV
昔から考えてたことに、**一体どんな変態的なプラットフォームでOpenCVを動かすことができるのだろう？**という興味がありました。
もともとARMデバイスでは数多くの成功例が報告されていましたが、この度MIPSのボード [Imagination Creator CI20](http://creatordev.io/ci20) を手に入れたので、その上でOpenCVをコンパイル、走らせてみました
![ci20-speed.png](https://qiita-image-store.s3.amazonaws.com/0/12162/ac8e07ef-13f7-95fd-ee0d-3d9494095aa8.png "CI20")
[CI20](http://creatordev.io/ci20)

ちなみに、OpenCVを走らせる事自体は色んな方が試されているので、そういう意味では二番煎じなのですが、せっかくなのでAdvent Calendar に投稿してみます

# クロスコンパイルとネイティブコンパイルについて
本題に入る前に、クロスコンパイルとネイティブ（？）コンパイルについて触れておきます。
通常、組み込みボード上での開発を行う場合、組み込みボードをターゲットシステム、それを制御、管理するパソコンをホストシステムと呼びます。
ターゲットシステムは組み込みなので、一般的にPCとはアーキテクチャが違い、ホストマシンのプログラムを直接ターゲットシステムに転送しても実行することはできません。
これを回避するには2つ方法があって、

 - クロスコンパイルによって違う命令セットのバイナリを生成する
 - ターゲットシステム上でコンパイルする

という方法があります。従来は前者が多かったのですが、近年はRaspberry Pi や CI20、Jetson、ODROIDなど、数々の組み込みボードが普通にLinuxを走らせられるようになっていることが多く、最近ではOpenCVをターゲットシステム上で直接コンパイルする機会も増えました

![crossCompile.png](https://qiita-image-store.s3.amazonaws.com/0/12162/9dac9e27-7dab-9fbb-b332-bc9514d9147e.png "クロスコンパイル")
![nativeCompile.png](https://qiita-image-store.s3.amazonaws.com/0/12162/178948a2-d765-e5ce-3cd9-5770fb6a692d.png "ネイティブコンパイル")

なお、OpenCV自体はクロスコンパイルを念頭に入れてcmakeが設計されており、```platforms```以下を覗くとクロスコンパイル用の設定ファイルが転がっていたりします
![platforms.png](https://qiita-image-store.s3.amazonaws.com/0/12162/2e8df9ce-33ee-849d-b27e-baf12c0cf2a0.png "クロスコンパイル用のコンフィグ")

それを流用すれば良いのですが、実際のところ、ARM用のコンパイラに対してSSEのオプションを渡す、64bit対応がされてない、などの細かな不具合がちらほらあり、そこそこの手修正が必要になります。なので可能であればネイティブに、開発ボード上でビルドするほうが幸せになれるでしょう。

# セットアップ
cmakeやgitなどを入れます。Debianがインストールされているので、```apt```でインストールできます

# ビルド
ビルド自体は通常のプロセスです

```
#cloneします
ci20@ci20:~$ git clone git@github.com:opencv/opencv.git opencv-fork

#3.1をチェックアウトします
ci20@ci20:~$ cd opencv-fork/
ci20@ci20:~/opencv-fork$ git checkout -b Branch_3_1_0 3.1.0
Switched to a new branch 'Branch_3_1_0'
HEAD is now at 92387b1 Fix java version++

#cmakeでMakefileを作ります
ci20@ci20:~/opencv-fork$ mkdir build
ci20@ci20:~/opencv-fork$ cd build/
ci20@ci20:~/opencv-fork/build$ time cmake ../

#ビルドします
ci20@ci20:~/opencv-fork/build$ time make -j 2 all
(中略)

real	209m34.010s
user	382m10.530s
sys	20m58.980s
```
**209分！？3時間半！？**とかすごい数字が表示されてます。

# テスト
重めの処理、```opencv_perf_imgproc```を実行してみます

```
ci20@ci20:~/opencv-fork/build$ time ./bin/opencv_perf_imgproc
(中略)
real    415m12.056s
user    495m1.930s
sys     14m45.530s
```
サクッと書いてますが、415分、ということはざっくり**7時間ぐらいかかります**。

# 実行してみての感想
CI20には、1.2GHzとは言え、SIMDも無い2コアのCPUが乗っています。また、GPUとして**PowerVR SGX540**が乗っていますが、惜しむらくはPowerVRは **SGX544**からOpenCL対応となっており、SGX540ではOpenCL(UMat)の恩恵も得ることができません。
つまりは、2コアのみで単純にPixel-by-Pixelの処理をする他なく、非力と言わざるを得ません。同様に組み込みの、安価なRaspberry Pi 3 などと比較してみても以下のようなパフォーマンス差です

機種|perf_impgrocの実行時間|値段
----|----|----
Raspberry Pi 3|92m52.330s|約50$
CI20|415m12.056s|約50£(65$)

この比較は、アーキテクチャもコア数もクロック周波数も違うので、直接的には意味のない比較ですが、処理性能/値段という意味ではあまり画像処理向きではない、という感覚が分かって貰えるかと思います。

もっとも、Creator CI20 は後継のCI40が発表されており、CI20/CI40ともに、[製品紹介のページ](http://creatordev.io/ci20)には**Cloud Connect**とか**IoT**みたいなキーワードが散りばめられております。なので、どちらかと言うと、ターゲットが組み込み**のIoT**、つまり重い処理はバックグラウンドに投げる想定をしており、むしろこのCPUにはそこまで期待してはいけない、ということなのかも知れません。

# 終わりに
本来、CI20を購入したきっかけはMIPSのSIMD命令、```MSA```をOpenCVに組み込んで、PRの数を稼ごうと思っていたから、なのですが購入して知ったのはCI20のCPU、XBurst はSIMD命令非対応だったという事です (買う前に気づけよ、と突っ込みたかった)。

というわけで、**OpenCVをビルドしただけの記事**でしたが、Advent Calendar の1日を埋めてみました。3日目は[fukushima1981](https://twitter.com/fukushima1981)先生の記事で「OpenCV完全体コンパイル難易度ランキング」です。お楽しみに！

# 備考
筆者は以下の環境で試しました

- CI20 (MIPS 32bit)
- OpenCV 3.1.0
- Debian 8.6
- cmake 3.0.2
- gcc 4.9.2