本日は
- Julia製の深層学習フレームワーク Flux.jl のアドベントカレンダー1日目の記事として執筆したものです.
Flux.jl Advent Calendar 2019 を作成しました。#Julia言語 #Qiita https://t.co/BLsZ7asCgB
— abap🌒(ᐡ ᐧ ﻌ ᐧ ᐡ) (@abap34) December 1, 2019
- Flux.jl ってみんな使ってるのかな? 空いてるところは abap 先輩が書くと信じて1日目は環境構築の方法を紹介します.
- ちなみに アドベントカレンダー参加方法はこちらを見るとやり方がわかります
- Julia全般のアドベントカレンダーは別個にあるらしいので我こそはーと思う方は是非書いてくださいな.
一年前を振り返る(ポエム)
- 私が Flux.jl を知ることになったのは1年前なんですが,レイヤーがCPUで動くんだけれどGPUで動かなかったりつらぽよ感がありましたが BatchNormレイヤーがGPUで動くようになったみたいなのでこれから始める方はそこまでストレスなくいけるんじゃないかなーと思います .
- まぁ,まだバージョンが0.10らしいのでこれからですよ.これから.
本題
- 環境構築をDockerで行うことを考えます.かつ NVIDIA の GPU が動く環境を構築しましょう.
- Dockerで. 「Docker CUDA」という言葉でぐぐると nvidia-docker っていう言葉/コマンドが出てくると思いますが,
NVIDIA Docker って今どうなってるの? (19.11版) にもあるように名前がコロコロ変わって,NVIDIA Container Toolkit という名前になってるようです.(まぁ nvidia docker って言葉がけっこうシミわかってるので通じると思います) - まっさらなホスト環境(これからDockerを入れていこうというマシーン環境を指す.ここでは NVIDIAの GPU 付きUbuntuマシーンを想定)から環境構築を始めるときは 同記事のセクション Docker 19.03 以降の環境で前だけを見て生きる場合に従えばOKです.つまり
- ホスト環境にNVIDIAのドライバーを入れる
- Dockerを入れる
- https://github.com/NVIDIA/nvidia-docker から導入
というステップを踏めばOKです.
Dockerfile
-
nvidia/cuda の DockerHub を探して適当なtagを探します.ここでは
10.0-cudnn7-devel-ubuntu18.04
としておきます.ドライバーが古いと怒られてしまう可能性があるのでnvidia-smi
などを見て対応するCUDAバージョンを確認するかかくじバージョンアップをしてください.
FROM nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04
MAINTAINER SATOSHI TERASAKI
RUN apt-get update && apt-get install -y \
build-essential \
libatomic1 \
python \
gfortran \
perl \
wget \
m4 \
cmake \
pkg-config \
git
ARG JL_VERSION="v1.3.0"
ARG WDIR="/root"
ARG JL_BUILD_DIR=$WDIR/build
WORKDIR $JL_BUILD_DIR
RUN echo "\
CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0\n\
prefix=/usr/local/julia-$JL_VERSION\n\
USE_BINARYBUILDER = 0\n\
" > Make.user \
&& cat Make.user \
&& git clone --depth=1 -b $JL_VERSION https://github.com/JuliaLang/julia.git julia-$JL_VERSION\
&& cp Make.user $JL_BUILD_DIR/julia-$JL_VERSION \
&& cd julia-$JL_VERSION \
&& make -j $(nproc) \
&& make install
RUN rm -r $JL_BUILD_DIR
ENV PATH=/usr/local/julia-$JL_VERSION/bin:$PATH
# runtime test
RUN julia -e "using InteractiveUtils; versioninfo()"
RUN julia -e 'using Pkg; Pkg.add(["Flux","CuArrays"]); using Flux'
CMD ["julia"]
- Juliaを無駄にソースからビルドしてるのは私の趣味なので公式ページのバイナリーのリンクを持ってきてコピーするでいいと思います.
- 例えば docker-library/julia を参照
使い方
ホスト環境にログインして次を実行します.
$ ls
Dockerfile
$ docker build -t fluxgpu .
$ docker run --gpus all --rm -it fluxgpu
sudo docker run --gpus all --rm -it fluxgpu
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.3.0 (2019-11-26)
_/ |\__'_|_|_|\__'_| |
|__/ |
julia> ; # to jump shell-mode
shell> nvidia-smi
Sun Dec 1 11:37:39 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.48 Driver Version: 410.48 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 1080 Off | 00000000:03:00.0 Off | N/A |
| 0% 45C P5 19W / 270W | 0MiB / 8119MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 1 GeForce GTX 1080 Off | 00000000:04:00.0 Off | N/A |
| 37% 46C P5 19W / 230W | 0MiB / 8118MiB | 4% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
上記のように nvidia-smi
コマンドの出力が出ればOKです.
一度 REPL モードに戻って次を実行してみましょう:
julia> using Flux
julia> d=Dense(100,1000)|>gpu
Dense(100, 1000)
julia> x=rand(Float32,100)|>gpu;
julia> typeof(x)
CuArray{Float32,1,Nothing}
julia> d(x)|>typeof
CuArray{Float32,1,Nothing}
julia> d(x) |> size
(1000,)
- これは Chainerでいえば
chainer.links.Linear
に相当するレイヤーですね.|> gpu
とすることでDense
レイヤーと データx
をGPUに移しています. - 畳み込みのレイヤーを担当する
Conv
への入力インターフェースは注意が必要です.ChainerですとNCHW
というデータレイアウトを採用していますが.Flux.jlでは逆でWHCN
とすることになります.例えばx=rand(Float32,224,224,3,1)|>gpu
というデータをJuliaでは投げることになります.
まとめ
- GPU 付きの環境をDockerで構築し Flux.jl を1年ぶりに動かしました.BatchNorm のforwardが動くのでまともなレイヤーが組めそうですね.
- 今回はとくにFluxのコンテキストはあまりないのでGPGPUをしたい人も各自でカスタマイズして活用できると思います.