Ubuntu16.04でHalideのチュートリアルを実行した際の環境設定ノート

# 目的
先日アメリカなどの国で[Pixel 2](https://store.google.com/us/product/pixel_2?hl=ja-JP)が発売になり、DxOスコアで98点をマークしたカメラ機能などが話題となった。[^1]
[^1]: 在米の私も早速購入した
また、Pixel 2には、新たに開発されたPixel Visual Coreという画像処理プロセッサが搭載されていることが明らかにされた
>[PC Watch: Google製スマホ「Pixel 2」は同社初の独自設計プロセッサを搭載](https://pc.watch.impress.co.jp/docs/news/1086734.html)

上記の記事によるとPixel Visual Coreは画像処理用ドメイン言語としてHalideをサポートし、開発者の負担を軽減しているとのことである。
このような状況から、今後Halideについての注目も大きくなると予想される。

Halideに関しては[詳しいチュートリアルも公開されている](http://halide-lang.org/tutorials/tutorial_introduction.html)が、私が手元の環境(Ubuntu16.4 64bit)で実行したところ思いのほか多数のトラブルに出くわしたので、その際に行った環境設定などの作業を公開する。

なお、これらの作業の中には環境設定を正しく行っておけば必要がないものも含まれているのではないかと想像する。もしそういったものがあった場合はコメントなどしていただければ感謝します。

# Halideについて
HalideはMITなどによって開発された画像処理用の言語である。特徴として画像処理の定義と、処理の最適化をわけることにより、非常に簡潔な表記のまま高性能を実現することができる。言語としてはC++を拡張したものとなっている。コンパイル済みのパッケージが配布されている実行プラットフォームはARM-Linux、X86-Linux (64-bit/32-bit)、Windows、Mac。最適化の対象としてはマルチコアCPU, NEON, SSE, AVX, GPUなどが挙げられている。
このページはHalideの実行環境設定に関するものなのでHalide自体の解説は他のくわしい記事に譲るものとする。解説などを含んだページとしては以下のようなものがあるようだ。

- [Halide - a language for image processing and computational photography](http://halide-lang.org)
本家Halideのホームページ。Halideの解説と詳細なチュートリアル、github上のバイナリーへのリンクなどがある。（なお、本稿でとりあげるチュートリアルはこのページのものである）

- [Qiita: Halide入門とOpenCVとの比較](https://qiita.com/fukushima1981/items/193c4ae03b2ea3b4f98e)
OpenCVとの比較を中心とした貴重な日本語によるHalideの解説。
（OpenCVとの速度比較なども行われていて、Halideに関する内容は本稿よりはるかに詳しいので、Halide自体を知りたい方はこちらのページを参照される事をおすすめします。

- [Qiita: Halideによる2次元FIRフィルタの実装]
(https://qiita.com/fukushima1981/items/c17688848ad6348ad579)
先ほどの「OpenCVとの比較」の方の別記事。実際にフィルターをどう書くか解説されている。


# 環境設定
## Halideのインストール
今回はコンパイル済みパッケージを使用した[^2]
[^2]: LLVMによるHalide自体のコンパイルも試したのだが、アプリケーションのリンク時のエラーが解消できなかったので、コンパイル済みパッケージを使用することにした
コンパイル済みのパッケージはこちらにある。
https://github.com/halide/Halide/releases
パッケージは実行環境とgccのバージョンに合わせて選択する必要がある。今回はX86 Linux 64bitのパッケージのうち、gcc-4.8に対応したものを選択した。（gccのバージョンについては後述する）
halide-linux-64-gcc48-で始まるファイルをダウンロードし、halideディレクトリを実行するディレクトリ（~/workなど）に解凍する。チュートリアルはhalide/tutorialフォルダ内にあり、このフォルダ内でコンパイル及び実行する限りは、特にパスの設定は必要ない。（コンパイル時および実行時に指定する）
なおこれ以降の作業はこの解凍したhalide/tutorialフォルダ内で行うものとする。


## アプリケーション用コンパイラの設定
Halideのコンパイル済みバイナリーはgcc5.3以前のバージョンしか対応していない。Ubuntu16.4のgccは5.4のようなので、以前のバージョンのgccとg++をインストールする必要がある。いくつかバージョンを試してみたが、gcc-4.8でアプリケーションのコンパイル、リンク、実行が成功したので、今回はそれを使用する。

```
sudo apt-get install gcc-4.8 g++-4.8
```

次にこちらのページを参考に使用するgccのバージョンを設定する
[Ask Ubuntu: Choose gcc and g++ version](https://askubuntu.com/questions/26498/choose-gcc-and-g-version)

具体的には以下のようにした。

```bash:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 10
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 20

sudo update-alternatives --remove-all cc
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30
sudo update-alternatives --set cc /usr/bin/gcc

sudo update-alternatives --remove-all c++
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30
sudo update-alternatives --set c++ /usr/bin/g++

sudo update-alternatives --config gcc
sudo update-alternatives --config g++
```

また、私の環境ではlibjepg-dev, libjpeg9-dev, libpng-devが無かったので追加した。

```bash:
sudo apt-get install libjpeg-dev libjpeg9-dev libpng-dev
```

このあたり追加が必要なライブラリーは環境によって異なると思われるので、各自必要なライブラリーを追加していただきたい。

さらにリンク時にtinfoが見つからないというエラーが出たため、以下のようなシンボリックリンクを作成した

```
sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.5 /lib/x86_64-linux-gnu/libtinfo.so
```

# Tutorial実行の注意点
Halideのチュートリアルはこちらにある。
http://halide-lang.org/tutorials/tutorial_introduction.html
また同じ内容が先ほどインストールしたHalideパッケージ内のtutorialフォルダーに含まれている。
基本的にチュートリアルで指示されているとおりにコンパイル用のコマンドをと実行用のコマンドを入力するだけなのだが、私の環境では若干の変更を入れないとエラーがでて実行できないケースがあった。

###02 Processing Images
コンパイル用のコマンドを元の

```
g++ lesson_02*.cpp -g -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -o lesson_02 -std=c++11
```

から、

```
g++ lesson_02*.cpp -g -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -o lesson_02 -std=c++11 -ljpeg
```

に変更（-ljpegの追加）

###07 Multi-stage pipelines
02 Processing Imagesと同様に-ljpegが必要

```
g++ lesson_07*.cpp -g -std=c++11 -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -o lesson_07 -ljpeg
DYLD_LIBRARY_PATH=../bin ./lesson_07
```

###09 Multi-pass Funcs, update definitions, and reductions
チュートリアル内ではこのように書かれている。
> On linux, you can compile and run it like so:

>```
g++ lesson_10*generate.cpp -g -std=c++11 -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_10_generate
LD_LIBRARY_PATH=../bin ./lesson_10_generate
g++ lesson_10*run.cpp lesson_10_halide.a -lpthread -ldl -o lesson_10_run
./lesson_10_run
```

しかし、私の環境ではHalideBuffer.hが見つからないというエラーなどが出たので以下のようにした。

```
g++ lesson_10*generate.cpp -g -std=c++11 -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_10_generate
LD_LIBRARY_PATH=../bin ./lesson_10_generate
g++ lesson_10*run.cpp lesson_10_halide.a -std=c++11 -I ../include -lpthread -ldl -o lesson_10_run
./lesson_10_run
```

二回目のg++の実行時に ```-I ../include```を追加されている。

###12 Using the GPU



まず、-ljpegを入れないと私の環境ではコンパイルされなかったので、追加

```bash
g++ lesson_12*.cpp -g -std=c++11 -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -lpthread -ldl -o lesson_12 -ljpeg
```

こうしてコンパイルしても、GPUに対応するOpenCLがインストールされていない場合はこのような実行結果だった

```
Testing performance on CPU:
1.0027 milliseconds
Not testing performance on GPU, because I can't find the opencl library
```

GPUと速度比較する場合はopenclをインストールしておく必要がある。私の環境ではNVIDIAのビデオカードを使用しているので、以下のようにしてインストールした。

```
sudo apt-get install nvidia-opencl-dev
```

OpenCLをインストール後は、次のような結果が表示された

```
Testing performance on CPU:
0.7788 milliseconds
Testing performance on GPU:
0.5871 milliseconds
```

思ったほど差がでないのは処理が軽いからだろうか。

###16 RGB images and memory layouts
以下の部分がチュートリアルの記述のままでは動作しなかった。

```
g++ lesson_16_rgb_run.cpp brighten_*.o -ldl -lpthread -o lesson_16_run
```

以下のように変更

```
g++ lesson_16_rgb_run.cpp brighten_* -ldl -lpthread -o lesson_16_run -I ../include -std=c++11
```

これですべてのチュートリアルを実行することができた。

なお、Halideのコンパイルが一通り終わった後は__コンパイラの設定を元にもどしておく__ことを強くおすすめする。[^3]

[^3]: 実は最初に実行した後で気が付かずひどい目にあった


```bash
sudo update-alternatives --config gcc
sudo update-alternatives --config g++
```

#まとめ
以上、Halideのチュートリアルを、Ubuntu16.04-64bitで実行した際の環境設定とそのほかの変更点を記録しておいた。