話題のC++用Deep Learningライブラリ「Flashlight」をWSL2上のDockerで動かしてHelloWorldしてみた

# はじめに
Twitterで以下のツイートが流れてきたので気になって調べてみました。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We&#39;re releasing Flashlight: A modern, open source machine learning library written entirely in C++. It&#39;s customizable to the core to support your research&#39;s needs — and it&#39;s pretty fast too. <a href="https://t.co/DIJd35Gt4u">https://t.co/DIJd35Gt4u</a> <a href="https://t.co/oGlgxTibVG">pic.twitter.com/oGlgxTibVG</a></p>&mdash; Facebook AI (@facebookai) <a href="https://twitter.com/facebookai/status/1383124825024176129?ref_src=twsrc%5Etfw">April 16, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

どうやらFacebookがC++用の機械学習ライブラリを出したようです。 
普段pytorchにお世話になっているのもあり、とりあえず動かしてみようと試みました。 
公式のDockerイメージがあるため動作確認は余裕だと思っていたのですが、時間をほどほどに溶かしてしまいました。
これからこのライブラリを触って動かしてみたいという人も現れると思うため、記事を書いてみた次第です。

この記事では、WSL2上に建てたdockerコンテナから[Flashlight](https://github.com/flashlight/flashlight)(CPU-backend)でHelloWorldをするまでを簡単に紹介しようと思います。 
流れとしては

1. WSL2の導入
2. WSL2上にDockerを導入
3. FlashlightでのHelloWorldの実行手順

となっています。
1~2を通しては改めて書く内容でもないため、記事の紹介程度で終わらせます。 
3に関しても基本的にはgitのREADMEに沿っています。ただ、Docker上で動かすまでのTutorialがなかったため、今回の記事にまとめています。
~~公式gitのDockerのセクションで「～for more information」とあるのですが、ここに飛んでもほとんど何も書かれていないスカスカのREADMEに飛ばされるだけでした~~

# 想定する人
+ とりあえず簡単に動かしてみたい人
+ C++まわりや機械学習初学者(つまり僕)

# 実行環境
* OS : Windows10 Home
* CPU : AMD Ryzen 9 3900X

# WSL2の導入
Windows上で動くubuntu(18.04.5)を導入します。 
すでに導入してある人はスキップしてください。

僕はこの記事を参考にしたらすんなりいけました。
[Windows10 WSL2にUbuntuをインストールする](https://rightxlight.co.jp/achievements/windows10-wsl2%E3%81%ABubuntu%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/)

こける場合はBIOSの仮想化が有効になっていない可能性があります。 
マザボのメーカーによって表示が違うので、ググってみてください。

# WLS2上にDockerを導入
こちらも紹介程度。

以下の記事を参考にしてみてください。 
記事内の「Dockerのインストール」をコピペしていけば簡単に導入できると思います。

[WSL2でDockerを動かしてみる](https://www.techceed-inc.com/engineer_blog/6671/)

# FlashlightでのHelloWorldの実行手順
基本コードは[元のgit](https://github.com/flashlight/flashlight)から拝借しています。 
以下ではいよいよFlashlightでHelloWorldプログラムを実行するまでを紹介します。

### コンテナを立てるまで
公式がDockerのイメージを公開してくれているのでこれを使いましょう。 

[公式イメージ](https://hub.docker.com/r/flml/flashlight/tags?page=1&ordering=last_updated&name=cpu-latest)

WLS2のターミナル上で以下を実行すれば勝手にイメージが作成されます。

```none
docker pull flml/flashlight:cpu-latest
```

正常に終了したら以下のコマンドでコンテナを作成し、中に入りましょう。

```none
sudo docker run --rm -itd --name flashlight flml/flashlight:cpu-latest
sudo docker exec -it flashlight bash
```

入ると`flashlight`というフォルダがあるのが見えると思います。これ以下にサンプルのコード等が入っています。
 
### HelloWorldプログラムのビルド

今回はこのライブラリを用いて自作のプロジェクトフォルダを作成し、サンプルコードをビルドするところまでを紹介したいと思います。 
個人的にサンプルコード(しかもbuild済)を動作させるだけでは、結局自分で書いたコードを動かしていくことができないと思いこのような形にしました。

まずはプロジェクトフォルダを用意します、名前は何でもいいです。 
また、実行場所はコンテナに入った時の場所(`/root`)で構いません。

```none
mkdir hello-flashlight
cd hello-flashlight
```

ここ(`hello-flashlight`)で以下のコードを作成してください。名前は`project.cpp`とします。

```cpp:project.cpp
#include <iostream>

#include <arrayfire.h>
#include <flashlight/fl/flashlight.h>

int main() {
 fl::Variable v(af::constant(1, 1), true);
 auto result = v + 10;
 std::cout << "Hello World!" << std::endl;
 af::print("Array value is ", result.array()); // 11.000
 return 0;
}
```

cmakeするためにCMakeLists.txtを作りましょう。 

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(myProject project.cpp)

find_package(flashlight CONFIG REQUIRED)
target_link_libraries(myProject PRIVATE flashlight::flashlight)
```

`hello-flashlight`以下に`build`フォルダを作り、その中でビルドを実行します。　
最後の`make -j4`の4はスレッド数を指定しているようなので、環境に合わせて数字を入れてください(今回は指定しなくてもうまくいくと思います)。

```none
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release  -DCMAKE_INSTALL_PREFIX=/opt/flashlight -DDNNL_DIR=/opt/onednn/lib/cmake/dnnl
make -j4
```

`cmake`で指定しているオプションですが、ライブラリの場所を指定しています。 
他の方法でflashlightをインストールする場合、カスタムしない限りはこのような指定は必要ありません。 
しかし、[元のDockerfile](https://github.com/flashlight/flashlight/blob/master/.docker/Dockerfile-CPU)を見てみると。

```\none:Dockerfile-CPU
RUN cd /root/flashlight && mkdir -p build && \
    cd build && cmake .. -DCMAKE_BUILD_TYPE=Release \
                         -DCMAKE_INSTALL_PREFIX=/opt/flashlight \
                         -DFL_BUILD_ALL_APPS=ON \
                         -DFL_BACKEND=CPU \
                         -DGloo_DIR=/opt/gloo/share/cmake \
                         -DDNNL_DIR=/opt/onednn/lib/cmake/dnnl && \
    make install -j$(nproc)
```

との記載があり、それぞれ必要なライブラリの場所が指定されているのが分かると思います。 
これに対応したパスを指定しなければならないということなんですね。 
~~弱者なのでここを特定するのに時間かかりました~~

上を実行すると`build`内に`myProject`という実行ファイルが生成されていると思います。 
これを`./myProject`で実行し以下が表示されれば成功です。

```none
Hello World!
Array value is
[1 1 1 1]
   11.0000
```

# おわりに
機械学習のライブラリですが、今回はHelloWorldの表示で終了とさせていただきました。 
しかし、自作のコードがビルドできればサンプル以外のものも動かして遊べるようになると思います。 
僕自身もこれから自分でモデルを作ってみて動かしてみようかなと考えています。 
その中でまた発見や問題点等あれば記事を書いてみようかなと。

ただその前にやはりpytorchとの速度比較もしてみたいので、exampleのMnistと同じモデルを作成し結果をまとめたものをまた記事にできたらいいなと思っています。