はじめに
Elixir の Nx を GPU 上で動かしたい
Nx を GPU で動かせば、 AI モデルもスイスイ動かせるはず
でも手元に GPU もないし、お金もない、、、
そんな人にオススメなのが Google Colaboratory です
ブラウザからコードを実行、結果を表示できます
基本無料で使用でき、 GPU や TPU まで使える最高のサービスです
え、 Python 用じゃないかって?
そう、 Google Colaboratory は Python の Jupyter Notebook をクラウド上で使用できるサービスです
が、実は Elixir Livebook も実行できてしまうのです
実装したノートブックはこちら(※Evisionを入れるための設定も含んでいます)
2023/08/02
Evision 0.1.33 リリースに伴い改訂
参考記事
準備
以下の二つのアカウントが必要になります
- Google アカウント
- ngrok アカウント
ngrok はローカルで起動した Web サービスを外部に公開できるサービスです
例えばローカルの http://localhost:8080 を https://xxxx-12-34-567-890.ngrok.io のような URL で一時的に外部からアクセスできるようにしてくれます
(もう何をやるか気づいた人は気付いたと思います)
ngrok にサインインしたら、左メニューの「Your Authtoken」を開き、
認証トークンを出しておいてください
Google Colaboratory での Livebook 起動
ランタイムの設定
Google Colaboratory で「ノートブックを新規作成」をクリックしてください
以下のような画面が開きます
GPU が使いたいので、ラインタイムを変更します
上メニューの「ランタイム」から「ラインタイムのタイプを変更」をクリックしてください
開いたモーダルで「GPU」を選択し、「保存」をクリックします
Erlang と依存パッケージのインストール
再生マークの右にある入力エリア(セル)に以下のコードを貼り付けてください
!echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
再生ボタンをクリック(=セルのコードを実行)して、しばらくすると左側に緑色のチェックマークが表示されます
Jupyter Notebook で !
を先頭に付けると、シェルコマンドを実行することができます
これを利用して、 Google Colaboratory のコンテナ上に Elixir をインストールするわけです
今実行したシェルコマンドは依存パッケージのインストール中にユーザー入力をしないための設定です
先ほどのセルの下辺あたりにマウスカーソルを持っていくと、「+コード」というボタンが出てくるのでこれをクリックします
(上に表示されている「+コード」ボタンでも良い)
すると、セルが一つ下に追加されるので、以下のコードを貼り付けてから、新しいセルを実行してください
apt-get
で Erlang と必要なライブラリをインストールします
!wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb && sudo dpkg -i erlang-solutions_2.0_all.deb
!sudo apt-get update -y
!sudo apt-get install -y erlang-base
!sudo apt-get install -y build-essential
!sudo apt-get install -y erlang-dev
!sudo apt-get install -y erlang-inets
!sudo apt-get install -y erlang-parsetools
!sudo apt-get install -y erlang-os-mon
!sudo apt-get install -y erlang-ssl
!sudo apt-get install -y erlang-xmerl
!sudo apt-get install -y libopencv-dev
インストールされた Erlang のバージョンを確認します
!erl -run halt
実行結果は以下のようになります
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit]
{"init terminating in do_boot",{undef,[{halt,start,[],[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({undef,[{halt,start,[],[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
asdf のインストール
Elixir は新しいものを使いたいので、 asdf を使います
まず asdf をインストールしましょう
GitHub から asdf をクローンします
!git clone https://github.com/asdf-vm/asdf.git ~/.asdf
asdf の実行ファイルにパスを通します
import os
os.environ['PATH'] = "/root/.asdf/shims:/root/.asdf/bin:" + os.environ['PATH']
Elixir のインストール
asdf で Elixir をインストールするため、プラグインを追加します
!asdf plugin add elixir
2023/08/02 時点の最新 Elixir 1.15.4 をインストールしますが、 Erlang のバージョンが 24 なので、それに合わせて 1.15.4-otp-24
を指定します
!asdf install elixir 1.15.4-otp-24
使用する Elixir のバージョンを 1.15.4-otp-24
に固定します
!asdf global elixir 1.15.4-otp-24
Elixir のバージョンを確認します
!elixir -v
実行結果は以下のようになります
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [jit]
Elixir 1.15.4 (compiled with Erlang/OTP 24)
Livebook のインストール
次のコードを実行して Livebook の最新版をインストールします
!mix local.hex --force
!mix local.rebar --force
!mix escript.install hex livebook --force
Elixir モジュールの依存パッケージ
Livebook で Evision を使う場合、 OpenCV の依存モジュールが必要になります
また、 Elixir Image を使う場合は libvips が必要になります
Livebook 上で使う Elixir モジュールの依存パッケージをインストールしておきます
!sudo apt-get install -y unzip ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libvips-dev
ngrok CLI のインストール
続いて ngrok のクライアントツールをインストールします
!curl -O https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
!unzip ngrok-stable-linux-amd64.zip
次のコードを実行すると、パスワード入力が表示されるので、準備しておいた ngrok の認証トークンを入力し、 Enter を押してください
from getpass import getpass
token = getpass()
入力した認証トークンの値を ngrok で使うように設定します
!./ngrok authtoken "$token"
次のコードを実行し、 ngrok でコンテナ内の http://localhost:8888
を外部公開します
get_ipython().system_raw('./ngrok http 8888 &')
!sleep 5s
次のコードを実行すると、公開された URL が表示されます
(ここでエラーが出る場合、 ngrok の認証トークンが誤っています)
!curl -s http://localhost:4040/api/tunnels | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])"
次のコードを実行し、 Livebook を 8888 ポートで起動します
!!/root/.asdf/installs/elixir/1.15.4-otp-24/.mix/escripts/livebook server --port 8888
うまくいけば Livebook が起動した旨表示され、セルが実行中の状態のままになります
URL の末尾についている ?token=<Livebook認証トークン>
の「Livebook認証トークン」の値が必要になるので、コピーしておきます
この状態で ngrok の外部公開 URL を開きます
認証を求められるので、先程コピーしておいた「Livebook認証トークン」を貼り付けて "Authenticate ->" をクリックします
はい、これで Livebook が開きました
Nx の実行
右上「New Notebook」をクリックして、新しいノートブックを開きます
Notebook dependencies and setup
のセルに以下のコードを貼り付け、実行してください
Mix.install(
[
{:benchee, "~> 1.1"},
{:nx, "~> 0.5"},
{:exla, "~> 0.5"},
{:torchx, "~> 0.5"},
{:evision, "~> 0.1.33"},
{:kino, "~> 0.10"}
],
system_env: [
{"XLA_TARGET", "cuda118"},
{"EXLA_TARGET", "cuda"},
{"LIBTORCH_TARGET", "cu116"},
{"EVISION_ENABLE_CUDA", "true"},
{"EVISION_ENABLE_CONTRIB", "true"},
{"EVISION_CUDA_VERSION", "118"}
]
)
system_env
で指定しているのは EXLA、 Torchx、 Evision が GPU を使うための環境変数設定です
しばらく時間がかかりますが、 Nx、 EXLA、 Torchx、 Evsion 等が GPU 用にインストールされます
次のコードを実行してみましょう
tensor = Nx.tensor([1, 2, 3], type: {:f, 64}, backend: Nx.BinaryBackend)
Nx.add(tensor, tensor)
バイナリバックエンドは正常に動いていますね
続いて EXLA です
EXLA.Backend の場合、 device_id
で何番目の GPU を使うか指定できます
tensor = Nx.tensor([1, 2, 3], type: {:f, 64}, backend: {EXLA.Backend, device_id: 0})
Nx.add(tensor, tensor)
CUDA で動いていることが分かります
Torchx でも同じようにしてみます
特に指定しなくても GPU を使いますが、 device: :cuda
で明示できます
tensor = Nx.tensor([1.0, 2.0, 3.0], backend: {Torchx.Backend, device: :cuda})
Nx.add(tensor, tensor)
初回実行だけ4分くらいかかりますが、無事 CUDA で動いています
Torchx の場合、デフォルトで GPU を使うようになっていても CPU 指定が可能です
tensor = Nx.tensor([1.0, 2.0, 3.0], backend: {Torchx.Backend, device: :cpu})
Nx.add(tensor, tensor)
最後に Evision です
tensor = Nx.tensor([1.0, 2.0, 3.0], backend: Evision.Backend)
Nx.add(tensor, tensor)
おわりに
これで GPU を使った Elixir の機械学習が捗りますね