【Jetson Nano】Jetson NanoにPyTorchをインストールしようとしてハマった話。


# はじめに

Jetson NanoにPyTorchをインストールしようとしたところ、
多少ハマったので、備忘の意味もこめて投稿します。
今では元気にPytorch & detectron2が動いています。
(dockerでインストールした方が早かった気がします。)

<!-- ----------------------------------------------------------- -->

# 目次

1. [前提](#前提)
2. [venv インストール&設定](#venv-インストール設定)
3. [jupyter-notebook インストール&設定](#jupyter-notebook-インストール設定)
4. [PyTorch インストール&設定](#pytorch-インストール設定)
5. [detectron2 インストール&実行](#detectron2-インストール実行)
6. [まとめ](#まとめ)

<!-- ----------------------------------------------------------- -->

# 前提

Jetson Nanoは`anaconda`が使えないので、`venv`と`jupyter notebook`を個別インストールした上で、
仮想環境上のノートブックに別PCから接続できるように設定します。
その上で、`PyTorch`と`detectron2`をインストールをすることで、
他の作業用PCからブラウザで遊べる推論環境の構築を目指します。

## 環境
- NVIDIA Jetson Nano
- CUDA: 10.2
- JetPack: 4.4
- KernelVersion: 4.9.140-tegra
- python2: 2.7.17
- python3: 3.6.9

<!-- ----------------------------------------------------------- -->

# venv インストール&設定

- venv インストール

venvが入っていなかったので、インストールします。一行。

```
user@hostname:~$ sudo apt install python3-venv
```

- 使い方 (ex. `new_env`という名前の仮想環境を作成 → `activate`)

```
user@hostname:~$ python -V
Python 2.7.17
user@hostname:~$ python3 -V
Python 3.6.9
user@hostname:~$ python3 -m venv new_env
user@hostname:~$ source new_env/bin/activate
(new_env) user@hostname:~$ 
(new_env) user@hostname:~$ python -V
Python 3.6.9

※deactivateするとき
(new_env) user@hostname:~$ deactivate
user@hostname:~$ 
```

以下、作成した仮想環境(new_env)にactivateした状態で作業しています。

<!-- ----------------------------------------------------------- -->

# jupyter-notebook インストール&設定

- jupyter-notebook インストール

主にこの記事を参考にさせていただきました。
https://vivinko.com/inoue/blog/2020/06/21/113534.html

うっかり必要なパッケージのインストールを忘れて思考停止で次のコマンドを打つと、
pipちゃんに、めちゃくちゃ文句言われます。

```
~$ pip install jupyter notebook
```

てことで、先に必要なパッケージのインストール。
(これを後回しにしたせいか、`pyzmq`が必要だのなんだの言われ、遠回りする羽目になりました。)
試行錯誤したので、結局何をすれば一発で通ったのかは分からないままですが、
[先人の教え](https://vivinko.com/inoue/blog/2020/06/21/113534.html)を見る限り、下のコマンドを実行していれば、たぶん大丈夫な気がします。

```
~$ sudo apt install libbz2-dev libsqlite3-dev libffi-dev python3-dev
~$ pip install jupyter notebook
```

- jupyter-notebook 設定

設定ファイルの作成、パスワードの設定、作業用ディレクトリの作成。

```
~$ jupyter notebook --generate-config
~$ jupyter notebook password
~$ mkdir ~/my-notebooks
```

設定ファイルの編集。

```~/.jupyter/jupyter_notebook_config.py
c.NotebookApp.allow_remote_access = True
c.NotebookApp.base_url = '/jetson/'
c.NotebookApp.open_browser = False
c.NotebookApp.ip = '0.0.0.0'
```

`base_url = '/jetson/'`とすることで、`http://[JetsonのIPアドレス]:8888/jetson/`でアクセスできるようにしています。
(他のデバイスのnotebookにもアクセスする予定なので、区別できるようにしています。)

- jupyter-notebookのサービス化(自動起動)

`/etc/systemd/system/jupyter.service`を作成し、以下の通り、編集します。
(`venv`を利用する場合の設定となっています。)
`{USER}`と`{GROUP}`は、自身のユーザ名とグループ名と置き換えて、
`{ENV}`は`venv`で作成した環境名を入力して下さい。

```/etc/systemd/system/jupyter.service
[Unit]
Description = Jupyter Notebook
[Service]
Type=simple
PIDFile=/var/run/jupyter-notebook.pid
ExecStart=/bin/bash -c ". /home/{USER}/{ENV}/bin/activate;jupyter-notebook --notebook-dir=/home/{USER}/my-notebooks"
WorkingDirectory=/home/{USER}/my-notebooks
User={USER}
Group={GROUP}
Restart=always
[Install]
WantedBy = multi-user.target
```

`venv`環境下でサービス化するときのポイントは、
　・`ExecStart`に、`activate` → `jupyter-notebook` 起動となるように記載すること
　・`jupyter-notebook`起動時の`--notebook-dir`と`WorkingDirectory`を一致させること
のようです。

後は、以下のコマンドで、`jupyter.service`の開始と自動起動設定。

```
~$ sudo systemctl start jupyter.service
~$ sudo systemctl enable jupyter.service
```

`systemctl enable jupyter.service`で、`active (running)`になっていればOKです。

<!-- ----------------------------------------------------------- -->

# PyTorch インストール&設定

必要なパッケージをインストールしてから、`PyTorch`をインストールします。

- opencv-python インストール

```
~$ pip install opencv-python
～～
No module named 'skbuild'
```

調べると、`pip`が古いときに言われる文句らしいので、
`pip`のアップデートをしてから、再度`opencv-python`インストール。

```
~$ pip install -U pip
～～
Uninstalling pip-9.0.1:
～～
Successfully installed pip-21.0.1

~$ pip install opencv-python
```

（`pip-9.0.1`…。そら文句言われるわ。アップデートの類は最初にしっかりしましょう…。）

- PyTorchインストール

[NVIDIA公式のフォーラム](https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-7-0-now-available/72048)を参考にインストールします。
`PyTorch`のversionはv1.7.0を選びました。

```
~$ wget https://nvidia.box.com/shared/static/cs3xn3td6sfgtene6jdvsxlr366m2dhq.whl -O torch-1.7.0-cp36-cp36m-linux_aarch64.whl
~$ sudo apt install python3-pip libopenblas-base libopenblas-dev libopenmpi-dev 
~$ pip install Cython
~$ pip install numpy torch-1.7.0-cp36-cp36m-linux_aarch64.whl
```

上記コマンドでインストールできるはずです。`libopenblas-dev`を足しています。
もし、`import torch`した際に、`Illegal instruction (core dumped)`と言われたら
`numpy`のversionが`1.19.5`の時に起こる問題の可能性があるので、([参考URL](https://forums.developer.nvidia.com/t/illegal-instruction-core-dumped/165488))

```
~$ pip uninstall numpy
~$ pip install numpy==1.19.4
```

で、`numpy`のversionを下げてください。

- torchvision インストール

`PyTorch`のversionに合わせて、インストールします。
[公式フォーラム](https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-7-0-now-available/72048)には、`PyTorch v1.7 - torchvision v0.8.1`の記載があるのですが、
フォーラムに記載の方法では、`v0.8.1`をインストールできなかったため、
`torchvision`は`v0.8.0`をインストールしていきます。

```
~$ sudo apt install libjpeg-dev zlib1g-dev libpython3-dev libavcodec-dev libavformat-dev libswscale-dev
~$ git clone https://github.com/pytorch/vision torchvision
~$ cd torchvision
~/torchvision$ git checkout v0.8.0
~/torchvision$ export BUILD_VERSION=0.8.0
~/torchvision$ python setup.py install
```

これで、`PyTorch`のインストールは完了です。

<!-- ----------------------------------------------------------- -->

# detectron2 インストール&実行

手元に`detectron2`で作成したモデルがあるため、ついでに`detectron2`もインストールします。

- detectron2 インストール

一行でインストール完了です。

```
~$ pip install 'git+https://github.com/facebookresearch/detectron2.git'
```

- detectron2 お試し

別のPCから、jupyter notebookにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185906/7878a34a-84c5-0d19-e10d-54fab0a5fbb6.png)
`torch.__version__`で、`Pytorch`のversion、
`torch.cuda.is_available()`で`cuda`の利用可否を表示しています。
無事、ご機嫌に動いています。

そのまま、サンプル画像を適当に引っ張ってきて、`matplotlib`で表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185906/ecdf4c25-fa1a-7f13-7258-410bc48502e1.png)
馬です。

まず、CPUで推論してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185906/fddf7536-a29d-0f4c-c466-6461703e362f.png)
`torch.device("cpu")`、`cfg.MODEL.DEVICE = "cpu"`を明示的に設定して推論実行。
推論完了まで、30秒程度。

次にGPUで推論してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185906/5b8f71f9-db0c-1785-361c-dedf7bdd39ad.png)
`torch.device("cuda:0")`、`cfg.MODEL.DEVICE = "cuda"`で実行します。
(そのままCPUのみ対応のデバイスに持っていけるように三項演算子で記載しています。)
推論完了まで、3.6秒程度。約8.3倍の速度で推論できました。

こちらの結果も`matplotlib`で表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185906/e0a7f243-d0d5-af91-a54e-3fc8d03f0aa3.png)
instance segmentationで、領域の推定ができています。

<!-- ----------------------------------------------------------- -->

# まとめ

Jetson NanoにPyTorch(& detectron2)をインストールできました。

[公式フォーラム](https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-7-0-now-available/72048)に、
> You can now download the [l4t-pytorch](https://ngc.nvidia.com/catalog/containers/nvidia:l4t-pytorch) and [l4t-ml](https://ngc.nvidia.com/catalog/containers/nvidia:l4t-ml) containers from [NGC](https://ngc.nvidia.com/catalog/all?orderBy=modifiedDESC&query=l4t&quickFilter=&filters=) for JetPack 4.4 or newer

の記載があるので、dockerで入れると一瞬だった気がしますが、気のせい、気のせい。


<!-- 
<a id="#reference"></a>
# 参考文献
- [リンクテキスト](URL)
- [リンクテキスト](URL)
-->