Visual Studio 2015でHalideを始める
Halideという画像処理向けのプログラミング言語を始めるべく
Visual Studio 2015でHalideの環境構築をしてみました
今回はその手順について紹介します
はじめに
HalideとはMITが開発している画像処理向けの言語です
公式ページやブログなどの紹介によると以下の特徴があるようです
簡単に処理を記述できて、尚且つ一度書いたコードを色んなターゲットで
高速に動かせるとしたら、とても魅力的ですね
リポジトリのREADMEによるとWindows(VS2015)にも対応しているようなので、
試しに導入してみることにしました
参考:
やること
- Visual Studio 2015でHalideをビルドする
- Halidを使った簡単なプログラムをビルド・実行する
事前に必要なもの
- Visual Studio 2015 Update 3 以降
- CMake
- libjpegとlibpng (画像ファイルを読み書きするtutorialを動かす場合)
ソースの入手
Halid
GitHubからHalidのリポジトリをクローンします
ここではD:\halideというディレクトリにソースを置くことにします
mkdir D:\halide cd D:\halide git clone https://github.com/halide/Halide.git
LLVMとClang
HalidのビルドにはLLVMとClangが必要になります
LLVM Download PageからLLVM source codeとClang source codeとダウンロードします
2017年4月22日の時点で最新バージョンは4.0.0でした
解凍してHalidのソースと同じディレクトリに置きます
$pwd D:\halide $ls Halide/ cfe-4.0.0.src/ llvm-4.0.0.src/
ビルド
LLVMのビルド
ソースと同じ場所にllvm-buildというディレクトリを作成しビルドを行います
まずはcmake
$mkdir D:\halide\llvm-build $cd D:\halide\llvm-build $cmake -DCMAKE_INSTALL_PREFIX=../llvm-install -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_TARGETS_TO_BUILD=X86;ARM;NVPTX;AArch64;Mips;Hexagon -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_BUILD_32_BITS=OFF -DCMAKE_BUILD_TYPE=Release ../llvm-4.0.0.src -G "Visual Studio 14 Win64"
次にビルド
MSBuild.exe /m /t:Build /p:Configuration=Release .\INSTALL.vcxproj
私の場合、MSBuild.exeへのパスが通ってなかったので環境変数の設定から
以下のディレクトリをPathに追加しました
C:Program Files (x86)\MSBuild\14.0\Bin
ビルドが終わるまでしばらく待ちます
CPU使用率が100%になってイイ感じ(?)です
Clangのビルド
LLVM同様、cmakeとビルドを行います
$mkdir D:\halide\clang-build $cd D:\halide\clang-build $cmake -DCMAKE_INSTALL_PREFIX=../llvm-install -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_TARGETS_TO_BUILD=X86;ARM;NVPTX;AArch64;Mips;Hexagon -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_BUILD_32_BITS=OFF -DCMAKE_BUILD_TYPE=Release ../cfe-4.0.0.src -G "Visual Studio 14 Win64" MSBuild.exe /m /t:Build /p:Configuration=Release .\INSTALL.vcxproj
Halideのビルド
最後にHalideをビルドします
$mkdir D:\halide\halide-build $cd D:\halide\halide-build $cmake -DLLVM_DIR=../llvm-install/lib/cmake/llvm -DLLVM_VERSION=37 -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 14 Win64" ../halide MSBuild.exe /m /t:Build /p:Configuration=Release .\ALL_BUILD.vcxproj
ビルドが完了するとhalide-build以下にHalideがインストールされています
私の場合、無事ビルド完了…と思いきやtutorialコードのビルドで失敗してしまいました
それについては余談で触れたいと思います
Halideのプロジェクトを作成してみる
ビルドできたらtutorialを実行するも良し、ですが
ここでは自分でHalideのプロジェクトを作成してみましょう
プロジェクト用ディレクトリを作成し、CMakeLists.txtとソースコードを置きます
halide_sample |- CMakeLists.txt |- main.cpp
CMake
CMakeLists.txtの中身はこんな感じです
Halide_DIRにHalideのインストール先を設定し
そこからヘッダとライブラリのパスを設定します
Halide.libもリンクしておきます
cmake_minimum_required(VERSION 2.8) set(Halide_DIR D:/halide/halide-build) include_directories(${Halide_DIR}/include) link_directories(${Halide_DIR}/lib/Release) file(GLOB srcs ./*.cpp ./*.h*) add_executable(sample ${srcs}) target_link_libraries(sample Halide)
ソース
main.cppの中身はこんな感じです
内容はtutorialのlesson_01_basics.cppから引っ張ってきました
Halide::FuncとHalide::Varで関数を記述し、realizeで呼び出すって感じでしょうか
#include <Halide.h> #include <iostream> int main() { Halide::Func gradient; Halide::Var x, y; gradient(x, y) = x + y; Halide::Buffer<int32_t> output = gradient.realize(3, 3); for (int i = 0; i < output.height(); i++) { for (int j = 0; j < output.width(); j++) { std::cout << output(i, j) << " "; } std::cout << std::endl; } return 0; }
プロジェクトの作成とビルド
cmakeを使ってプロジェクトの作成とビルドを行います
$mkdir build $cd build $cmake .. -G "Visual Studio 14 Win64" cmake --build . --config Release
実行結果
ちゃんと (x, y) = x + y という結果になってました
0 1 2 1 2 3 2 3 4
おわりに
今回はVisual Studio 2015でHalideの環境構築するところまでを紹介しました
今後はより複雑なアルゴリズムの記述や、高速化の方法について調べてみようと思います
【余談】tutorialのビルドにハマった話
私の場合、tutorialのビルド時に以下のようなビルドエラーに遭遇してしまいました
ビルドエラーは画像ファイルを読み書きするtutorial(lesson_02,07,09,12)で起きてました
Halide/tutorialのCMakeLists.txtを見ると、これらのサンプルはlibjpegとlibpngが入ってないと
ビルドされないはずなのですが、libjpegとlibpngなんて入れたっけなあ…
と思ってたら、どうやらAnaconda2(python環境)を入れた際に一緒に入ってたみたいです
__iob_funcの未定義
これについては、ググると回避方法が見つかりました
Halide/tools/halide_image_io.hで__iob_funcを定義してやります
FILE _iob[] = { *stdin, *stdout, *stderr }; extern "C" FILE * __cdecl __iob_func(void) { return _iob; }
参考:
sprintfの未定義
なんでsprintfが未定義なの?ってのが謎ですが
どっかに定義されてるだろってことで、extern宣言したら回避できました(適当)
これもhalide_image_io.hに書いてます
extern "C" int sprintf ( char * str, const char * format, ... );
NT32の再定義
どうやらINT32がlibjpgのjmorecfg.hと、Windows Kits\8.1\Include\shared\basetsd.hで
両方定義されちゃってるようです
jmorecfg.hをみると、INT32はQGLOBAL_Hが定義されていない場合に定義されるようです
そこで、halide_image_io.hでjpeglib.hをインクルードする前にQGLOBAL_Hを定義してやります
#ifndef HALIDE_NO_JPEG #define QGLOBAL_H #include "jpeglib.h" #undef QGLOBAL_H #endif
以上でビルドエラーを回避することができましたが、かなり適当なのでご参考までに