AnacondaでGPU対応のTensorFlowをインストールする簡単な方法

## はじめに
本記事は、Anacondaを使用してGPU対応のTensorFlowを導入する際に、お手軽にインストールする方法について解説します。

本記事の前提知識は、以下の2点です。
- GPUドライバの適切なインストールされている（`nvidia-smi`が動作している）
- Anacondaがインストールされていてる

なお、筆者の実装環境は`Ubuntu 22.04`です。

## 最初に確認しておくこと

### `nvidia-smi`が認識できるかチェック

以下のコマンドでGPUドライバが認識できるかを確認します。
```
$ nvidia-smi       
Wed Nov 22 20:04:05 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03             Driver Version: 535.129.03   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
# ---出力結果省略---
```

この結果にはGPUのメタ情報とともに`Driver Version: XXX`と`CUDA Version: XXX`が表示されます。`CUDA Version`は`Driver Version`がサポートするCUDAの最大バージョンです。**このDriverのバージョン確認は重要で、適切なTensorFlowのバージョンがこれに依存します**。

※この時、`nvidia-smi`で、`command not found`や`Failed to initialize NVML`などのエラーが表示される場合は、GPUドライバが正常にインストールされていない可能性があります。この場合はドライバのインストールから始める必要がありますが、本記事ではその詳細は割愛します。

### Anacondaが入っているかチェック

以下のコマンドでAnacondaがインストールされているかを確認します。

```
$ conda --version
conda 23.5.2
```

これによってAnacondaのバージョンが表示されれば、Anacondaが正常に機能しています。もし`conda: Command not found.`などのエラーが表示された場合は、Anacondaをインストールする必要がありますが、その詳細は本記事では省略します。


## GPU対応のTensorFlowの環境作成

このセクションでは、Anacondaを使用して初めてGPU対応のTensorFlowを導入する手順を説明します。

### Anaconda仮想環境にTensorFlowをインストール
AnacondaでGPU対応のTensorFlowを導入するには、以下のコマンドを使用します。

```
$ conda create --name tf-gpu-env tensorflow=*=gpu_*
```

これにより、適切なバージョンのTensorFlow、CUDA（GPUで使う）、cuDNN（GPUで使う）、PythonなどのGPUでTensorFlowを使う上で必要なライブラリが一緒に互換性を考慮してインストールされます。

なお、本記事では仮想環境の名前を`tf-gpu-env`としていますが、環境名は任意に変更可能です。

**TensorFlowのような大規模なライブラリを扱う際には、新しい環境（他のライブラリを入れていない環境）を作成し、そこに最初にインストールする**ことでエラーが起きにくくなると思います。

:::note info
Anacondaに慣れている方は、`conda search tensorflow`と入力して表示されるバージョンの中から`Build Channel`が`gpu_XXXX`となっているものを選択して、適切なTensorFlowのバージョンを指定することもできます。
:::

### TensorFlowのGPU認識の確認

インストールが完了したら、GPUが正常に動作しているか確認します。まず、`conda activate tf-gpu-env`を使用して仮想環境に入ります。

次に、以下のPythonコードを使用してGPUが動作しているかを確認します。

```python:tensorflow_gpu_check.py tensorflowでGPUが動いているか確認
import tensorflow as tf

# GPUが使えているか確認
print('GPU is available: ', tf.test.is_gpu_available())
```
```:出力結果
# 略
GPU is available: True
```

と出ていればGPUが正常に動作しています。これで終わりです。折りたたみ部分はスキップして大丈夫です。

`GPU is available: False`のような結果が表示された場合は、CUDAのバージョンとGPUドライバのバージョンの依存関係に問題がある可能性があります。その場合は折りたたみの箇所に進みます。

<details>


<summary>GPU is available: Falseと出た場合の解決方法</summary>


### GPUが使えない(`False`)が出た場合
#### GPUドライバのバージョンとCUDAのバージョンの確認
まず、`tensorflow`を入れた環境（本記事の例では`tf-gpu-env`）に入った状態で、以下のコードを使用してCUDAのバージョンを確認します。ここで表示されるTensorFlowのバージョンは後の手順で使用します。

```
$ conda list | grep -E 'cudatoolkit|tensorflow'
cudatoolkit               11.3.1               h2bc3f7f_2  
tensorflow                2.12.0          gpu_py39hc0f3f85_0  
tensorflow-base           2.12.0          gpu_py39h24d65da_0  
tensorflow-estimator      2.12.0           py39h06a4308_0  
```

次に、`nvidia-smi`を実行し、表示される`CUDA Version`を確認します。この時、`conda list`で表示された`cudatoolkit`のバージョンが、`CUDA Version`よりも大きい場合が考えられます。その場合は次の手順に進みます。

※`nvcc --version`で表示されるバージョンがCUDAのバージョンとならないので注意してください。詳細は[補足](#補足)をご覧ください。

#### 仮想環境を消してtensorflowのバージョンをダウングレード

このとき、`cudatoolkit`だけをダウングレードすればいいというわけではありません。`cudatoolkit`は`tensorflow`や他のライブラリと依存関係にあるため、ハマる可能性があります。そのため、一度仮想環境を削除し、適切なバージョンの`tensorflow`を指定して再インストールします。

仮想環境から`deactivate`して`GPU is available: False`と表示された環境を削除します。

```
$ conda deactivate
$ conda remove --name tf-gpu-env --all
```

仮想環境が削除できたら、以下のコマンドを入力してAnacondaが利用可能なGPU対応のtensorflowを確認します。

```
$ conda search tensorflow | grep gpu_
# 略
tensorflow                    2.10.0 gpu_py310hb074053_0  pkgs/main           
tensorflow                    2.10.0 gpu_py37h84cb581_0  pkgs/main           
tensorflow                    2.10.0 gpu_py38h11b98a5_0  pkgs/main           
tensorflow                    2.10.0 gpu_py39h039f4ff_0  pkgs/main           
tensorflow                    2.11.0 gpu_py310hf8ff8df_0  pkgs/main           
tensorflow                    2.11.0 gpu_py38hec62255_0  pkgs/main           
tensorflow                    2.11.0 gpu_py39h6d58c08_0  pkgs/main           
tensorflow                    2.12.0 gpu_py310hfda07e1_0  pkgs/main           
tensorflow                    2.12.0 gpu_py311h65739b5_0  pkgs/main           
tensorflow                    2.12.0 gpu_py38h03d86b3_0  pkgs/main           
tensorflow                    2.12.0 gpu_py39hc0f3f85_0  pkgs/main    
```
このように異なるバージョンの`tensorflow`が表示されます。例えば、[GPUが使えない(False)が出た場合](#gpuが使えないfalseが出た場合)で表示されたバージョンが2.12だとすると、それよりも低いバージョンの2.11をインストールする場合は次のようにします。

```
conda create --name tf-gpu-2.11-env tensorflow=2.11.0=gpu_*
```

インストールが完了したら仮想環境に入り、再び[TensorFlowのGPU認識の確認](#tensorflowのgpu認識の確認)の手順に戻り、GPUが正常に認識されるか確認します。必要に応じて、再帰的にTensorFlowのバージョンをダウングレードしていくことで、基本的にはこれでGPUが使えるようになると思います。

</details>

## まとめ
本記事では、Anacondaを使用してGPU対応のTensorFlowを導入する手順について解説しました。

ポイントとしては、以下の2点です。

- GPUドライバの対応したバージョンのtensorflowを使う。
- 仮想環境を作成時（他のライブラリを入れていない環境）にインストールする。

GPUでTensorFlowを動かしてみたい方の一助になれば幸いです。

## 補足
### `nvcc --version`のCUDAのバージョンとの違いについて

CUDAのバージョンを理解するとき、`nvcc`との関係を抑えておく必要があります。`nvcc`と`cudatoolkit`の用語の意味は以下のようになります。

- nvcc: NVIDIA CUDA Compilerの略で、CUDAのコンパイラです。CUDAプログラムをコンパイルしてGPU上で実行可能なバイナリに変換します。`nvcc --version`は、基本的にシステム全体のCUDAバージョンを示します。`wihch nvcc`で確認すると使われている`nvcc`のパスを確認できます。

- cudatoolkit: NVIDIAが提供するCUDAのソフトウェア開発キットです。これには`nvcc`などのツールやCUDAランタイムライブラリなどが含まれます。通常、ユーザーはこれを直接使うことはありませんが、CUDAアプリケーションをビルドするためには必要です。

Anaconda環境では`cudatoolkit`が専用に提供されており、これがAnaconda内で使用されるCUDAバージョンとして機能します。したがって、`nvcc --version`で表示されるのはシステム全体のCUDAバージョンであり、Anaconda環境内で動作するTensorFlowなどのライブラリは、Anaconda内に導入された`cudatoolkit`を使用します。
そのため、`nvcc --version`はシステム全体のCUDAバージョンを示すことになり、Anaconda環境内で実際に動作するCUDAバージョンとは違う場合があります。

実際にTensorFlowで使われているCUDAバージョンをPythonで確認するには、以下のコードを使います。

```python:使用されているCUDAバージョンの確認
import tensorflow as tf

sys_details = tf.sysconfig.get_build_info()
cuda_version = sys_details["cuda_version"]
print('cuda_version: ', cuda_version)
```

### `tensorflow-gpu`でインストールするときは`numpy`エラーに注意
AnacondaでGPU対応のTensorFlowをインストールするもう一つの方法として、`tensorflow-gpu`を使う手がありますが、`numpy`のバージョンでハマることがあるので注意が必要です。

以下に、この問題に遭遇した具体的なケースを紹介します。

まず、次のコマンドを使用して`tensorflow-gpu`をインストールします。この手順でCUDA、cuDNN、PythonなどTensorFlowで必要となるモジュールが同時にインストールされます。

```
$ conda create -n tf-gpu-env2 tensorflow-gpu
```

インストールが完了したら、作成した仮想環境に`activate`して入ります。

```
$ conda activate tf-gpu-env2
```

Pythonで`import tensorflow`を実行します。この時、以下のエラーが発生する可能性があります。

```
AttributeError: module 'numpy' has no attribute 'object'.
`np.object` was a deprecated alias for the builtin `object`. To avoid this error in existing code, use `object` by itself. Doing this will not modify any behavior and is safe. 
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
```

このエラーは、`numpy`と`tensorflow`のバージョンの互換性に関するものです。仮想環境で`tensorflow-gpu`を構築した場合でも、互換性の問題が発生する可能性があるため、注意が必要です。

詳細は下記の記事にまとめておりますので、良かったらそちらをご覧ください。

https://qiita.com/yusuke_s_yusuke/items/bf7ce2deb6153ab0123b


### 他のライブラリも使う場合
TensorFlow以外のライブラリも一緒に使いたい場合、仮想環境を構築する際に同時にインストールしておくと、比較的スムーズに環境を構築できると思います。ただし、この方法が必ずしも問題なく機能するわけではなく、エラーが発生したりバージョン指定が必要な場合もありますので、注意が必要です。

例えば、[OpenCV](https://opencv.org/)を一緒に使用したい場合は、以下のようにコマンドを記述します。

```
conda create --name tf-gpu-opencv-env tensorflow=*=gpu_* opencv
```

これにより、`tensorflow`と`opencv`が同時にインストールされた仮想環境が作成されます。必要に応じて他のライブラリも同様に指定してインストールできます。

## 参考資料

https://qiita.com/ktokey/items/7ee9c112198a6b0b5709

https://qiita.com/yukoba/items/c4a45435c6ee5d66706d

https://stackoverflow.com/questions/56470424/nvcc-missing-when-installing-cudatoolkit

https://stackoverflow.com/questions/73270806/conda-env-downgrade-nvcc

https://stackoverflow.com/questions/75353067/attributeerror-module-numpy-has-no-attribute-object