Jetson NanoにPyTorch Geometricを導入

## 概要
Jetson NanoにPytorch Geometricを導入する方法とその過程でつまずいた点をまとめた記事となっています。

## 環境
|名称|バージョン|
|:--:|:--:|
|Jetson NX Developer Kit SD Card Image|JP 4.4|
|Ubuntu|18.04.4 LTS|
|pip|21.0.1|
|torch|1.6.0|
|torchvision|0.7.0a0+78ed10c|
|torch-geometric|1.6.3|
|numba|0.52.0|
|numpy|1.19.4|
|scikit-learn|0.24.0|
|Cython|0.29.21|
|Pillow|8.0.1|
|h5py|3.1.0|

pip3 listの詳細は[こちら](https://github.com/UchiyKei1320/JetsonNano/blob/main/piplist.txt)にまとめています。

## PyTochとtorchvisionの導入
[NVIDIAの公式サイト](https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-7-0-now-available/72048)を参考にJetsonNanoにPyTorchとtorchvisionを導入します。
その際、PyTorchとtorchvisionのバージョンは下記表のように揃える必要があります。

|PyTorch|torchvision|
|:--:|:--:|
|v1.4|v0.5.0|
|v1.5|v0.6.0|
|v1.6|v0.7.0|
|v1.7|v0.8.1|

## PyTorch Geometric
[PyTorchgeometricの公式サイト](https://pytorch-geometric.readthedocs.io/en/latest/notes/installation.html)を参考にJetsonNanoにPyTorchgeometricを導入します。
`pip3 install torch-geometric`を実行すると、おびただしい数のエラーが出力されると思います。

まず、最初のエラーとして下記のようなものがあります。

```text:error0
  numpy/core/src/multiarray/numpyos.c:18:10: fatal
error: xlocale.h: No such file or directory
     #include <xlocale.h>
              ^~~~~~~~~~~
    compilation terminated.
```

[こちら](https://github.com/biobakery/homebrew-biobakery/issues/31)を参考にして、下記コマンドを実行することで、シンボリックを作成します。

```text:command0
ln -s /usr/include/locale.h /usr/include/xlocale.h
```


次に、下記のようなものがあります。（一部抜粋）

```text:error1
  compile options: '-I/usr/include -I/usr/include/python3.6m -c'
  extra options: '-std=c++11'
  aarch64-linux-gnu-gcc: numba/np/ufunc/tbbpool.cpp
  aarch64-linux-gnu-gcc: numba/np/ufunc/gufunc_scheduler.cpp
  numba/np/ufunc/tbbpool.cpp:31:2: error: #error "TBB version is too old, 2019 update 5, i.e. TBB_INTERFACE_VERSION >= 11005 required"
   #error "TBB version is too old, 2019 update 5, i.e. TBB_INTERFACE_VERSION >= 11005 required"
    ^~~~~
```

「TBBのバージョンが古すぎるよ」と言われています。そこで、[こちら](https://forums.developer.nvidia.com/t/install-python-packages-librosa-jetson-tx2-developer-kit-problem/126337/3)と[こちら](https://forums.developer.nvidia.com/t/cuda-toolkit-version-problem-when-trying-to-run-a-python-script-on-gpu-through-numbas-jit-cuda-modules-on-agx-xavier/129469/4)を参考に下記コマンドを実行します。

```text:command1
sudo mv /usr/include/tbb/tbb.h /usr/include/tbb/tbb.bak
```


2つ目のエラーとして下記のようなものがあります。（一部抜粋）

```text:error2
  LLVM version... Traceback (most recent call last):
    File "/tmp/pip-install-j9tfftg5/llvmlite_b94d9fd8fa1b4f3ba5ec9616f5781922/ffi/build.py", line 105, in main_posix
      out = subprocess.check_output([llvm_config, '--version'])
    File "/usr/lib/python3.6/subprocess.py", line 356, in check_output
      **kwargs).stdout
    File "/usr/lib/python3.6/subprocess.py", line 423, in run
      with Popen(*popenargs, **kwargs) as process:
    File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
      restore_signals, start_new_session)
    File "/usr/lib/python3.6/subprocess.py", line 1364, in _execute_child
      raise child_exception_type(errno_num, err_msg, err_filename)
  FileNotFoundError: [Errno 2] No such file or directory: 'llvm-config': 'llvm-config'
```

「llvm-configというディレクトリが無いよ」と言われています。
そこで、[こちら](https://github.com/numba/llvmlite/issues/621)を参考に下記コマンドを実行します。

```text:command2
sudo apt-get install llvm-8-dev
sudo ln -s /usr/bin/llvm-config-8 /usr/bin/llvm-config
pip3 install numba --user
```


3つ目のエラーとして下記のようなものがあります。（一部抜粋）

```text:error3
  Traceback (most recent call last):
    File "/tmp/pip-install-lkm3cfsk/llvmlite_ad80c4602e57429a991c3cab3cc36994/ffi/build.py", line 191, in <module>
      main()
    File "/tmp/pip-install-lkm3cfsk/llvmlite_ad80c4602e57429a991c3cab3cc36994/ffi/build.py", line 181, in main
      main_posix('linux', '.so')
    File "/tmp/pip-install-lkm3cfsk/llvmlite_ad80c4602e57429a991c3cab3cc36994/ffi/build.py", line 143, in main_posix
      raise RuntimeError(msg)
  RuntimeError: Building llvmlite requires LLVM 10.0.x or 9.0.x, got '8.0.0'. Be sure to set LLVM_CONFIG to the right executable path.
  Read the documentation at http://llvmlite.pydata.org/ for more information about building llvmlite.
```

「llvmliteのビルドに必要なLLVMのバージョンが違うよ」と言われています。

そこで、[こちら](https://askubuntu.com/questions/1286131/how-do-i-install-llvm-10-on-ubuntu-18-04)を参考に下記コマンドを実行します。

```text:command3
sudo apt-get install llvm-10*
cd /usr/bin
rm llvm-config
ln -s llvm-config-10 llvm-config
```

3つ目のエラーとして下記のようなものがあります。（一部抜粋）

```text:error4
    lto1: fatal error: bytecode stream in file ‘build/freetype-2.6.1/objs/.libs/libfreetype.a’ generated with LTO version 7.3 instead of the expected 6.2
    compilation terminated.
    lto-wrapper: fatal error: aarch64-linux-gnu-g++ returned 1 exit status
    compilation terminated.
    /usr/bin/ld: error: lto-wrapper failed
    collect2: error: ld returned 1 exit status
    error: command 'aarch64-linux-gnu-g++' failed with exit status 1
```

このエラーは、gccのバージョンが8.4.0の時に発生します。バージョンを7.5.0にしたらうまく行きました。[こちら](http://www.neko.ne.jp/~freewing/raspberry_pi/nvidia_jetson_install_gcc_8_4_0/)のサイトを参考にバージョンの切り替えを行います。

```text:command4
sudo update-alternatives --config gcc
sudo update-alternatives --config g++
```

これで、全てのエラーを消化できました。再び`pip3 install torch-geometric`でPyTorch Geometricを入れましょう。


### サンプルプログラム
PyTorch Geometricが正常に動作しているか確認するため、下記のサンプルプログラムを実行します。

```python:pytorch_geometric_sample.py
import torch
from torch_geometric.data import Data

edge_index = torch.tensor([[0, 1, 1, 2],[1, 0, 2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)

data = Data(x=x, edge_index=edge_index)
print(data)
```

```text:実行コマンドと出力結果
python3 pytorch_geometric_sample.py
Data(edge_index=[2, 4], x=[3, 1])
```

成功です！

## 最後に一言
僕がこの問題を解決したのは随分前のことで、どこでつまずいたかを思い出すのに非常に苦労しました。
今後はそのような苦労をしないために、すぐに記事化する必要がありそうですね。

## 参考文献
https://pytorch-geometric.readthedocs.io/en/latest/notes/installation.html
https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-7-0-now-available/72048
https://github.com/biobakery/homebrew-biobakery/issues/31
https://github.com/h5py/h5py/issues/1461
https://github.com/numba/numba/issues/6605
https://forums.developer.nvidia.com/t/cuda-toolkit-version-problem-when-trying-to-run-a-python-script-on-gpu-through-numbas-jit-cuda-modules-on-agx-xavier/129469/4
https://github.com/NVIDIA/tacotron2/issues/374
https://github.com/rusty1s/pytorch_geometric/issues/1214
https://github.com/keras-team/keras-tuner/issues/317
https://stackoverflow.com/questions/59474533/modulenotfounderror-no-module-named-numpy-testing-nosetester
https://askubuntu.com/questions/1286131/how-do-i-install-llvm-10-on-ubuntu-18-04
https://pytorch-geometric.readthedocs.io/en/latest/notes/introduction.html
http://www.neko.ne.jp/~freewing/raspberry_pi/nvidia_jetson_install_gcc_8_4_0/
https://github.com/scipy/scipy/issues/11329