レガシーマシンでもStable Diffusionを使いたい

# はじめに
数ヶ月前、「NVIDIA Tesla K20」というサーバー用のグラフィックボードをジャンク品として、税込み2480円で購入しました。
2012年に発売されたKeplerアーキテクチャ搭載のグラフィックボードで、Geforce600番台と同世代というかなり骨董品になります。

今回はそんなレガシーマシンを使用し、Stable Diffusionで画像を生成するまでの過程を紹介します。

# 実行環境

|項目  |内容| 
|---|---|
|CPU  |Intel(R) Xeon(R) CPU E5-1660 (6c 12t 3.90 GHz)  |
|GPU |NVIDIA Tesla K20 |
|メモリー（仮想マシン） |16GB  |
|マザーボード |Intel DX79TO  |
|OS（仮想マシン）|Ubuntu 20.04.6 LTS |

簡単に環境を壊せるようにProxmoxで仮想マシンを作成し、パススルーで対象のGPUを繋いでいます。

```shell
$ lspci | grep -i nvidia
01:00.0 3D controller: NVIDIA Corporation GK110GL [Tesla K20c] (rev a1)
```

# Nvidiaドライバー周りのインストール

NVIDIA Tesla K20が対応しているnvidia-driverのバージョンは470までなので、「nvidia-driver-470」をインストールします。

```shell
$ sudo apt update -y
$ sudo apt upgrade -y
$ sudo apt install ubuntu-drivers-common
$ ubuntu-drivers devices
$ sudo apt install nvidia-driver-470
```
再起動後、

```shell
$ nvidia-smi
Sun Dec 29 10:50:33 2024
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.256.02   Driver Version: 470.256.02   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K20c          Off  | 00000000:06:10.0 Off |                    0 |
| 30%   39C    P0    53W / 225W |      0MiB /  4743MiB |    100%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

と表示されれば、Nvidia Driverのインストールは完了です。
つぎに、CUDA Toolkitをインストールします。[NVIDIA DEVELOPER](https://developer.nvidia.com/cuda-11-4-0-download-archive?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=20.04&target_type=deb_local)にアクセスして、ダウンロードとインストール方法を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/835335/b0a6618e-ad72-aa22-8445-7ab12db9f31e.png)
ページに書かれてる方法に従って、ダウンロードとインストールを行います。
インストール完了して再起動後、`~/.bashrc`に
```shell
export PATH=/usr/local/cuda:/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/cuda/lib64:$LD_LIBRARY_PATH
```
を追記し、`source .bashrc`で変更を確定します。最後に
```shell
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Wed_Jun__2_19:15:15_PDT_2021
Cuda compilation tools, release 11.4, V11.4.48
Build cuda_11.4.r11.4/compiler.30033411_0
```
でバージョンの確認が出来ればCUDA Toolkitのインストールが完了となります。

最後にCuDNNをインストールをします。[cuDNN Archive](https://developer.nvidia.com/rdp/cudnn-archive)にアクセスをして、CUDA 11.4に対応したバージョンをダウンロードします。今回は`Download cuDNN v8.9.7   (December 5th, 2023), for CUDA 11.x`の`Local Installer for Ubuntu20.04 x86_64 (Deb)`をダウンロードしました。
ダウンロード後、
```shell
$ sudo apt-get install zlib1g
$ sudo dpkg -i cudnn-local-repo-ubuntu2004-8.9.7.29_1.0-1_amd64.deb
$ sudo cp /var/cudnn-local-repo-ubuntu2004-8.9.7.29/cudnn-local-CD2C2DD4-keyring.gpg /usr/share/keyrings/
$ sudo apt update
$ sudo apt -y install libcudnn8 libcudnn8-dev
```
でCuDNNのインストールをします。インストール後
```shell
$ dpkg -l | grep cudnn 
ii  cudnn-local-repo-ubuntu2004-8.9.7.29  1.0-1                             amd64        cudnn-local repository configuration files
ii  libcudnn8                             8.9.7.29-1+cuda11.8               amd64        cuDNN runtime libraries
ii  libcudnn8-dev                         8.9.7.29-1+cuda11.8               amd64        cuDNN development libraries and headers
```
と出ればインストール完了です。（cuDNNのバージョンの後ろに「cuda11.8」と書かれていますが、問題はありません）

# Python3.10のインストール

PyTorchが対応しているPythonのバージョンは`3.9, 3.10, 3.11`なので、他のライブラリの兼ね合いから`3.10`をインストールします。
```shell
$ sudo apt install -y software-properties-common
$ sudo add-apt-repository ppa:deadsnakes/ppa
```
2行目を実行したあとに
```shell
For nightly builds, see ppa:deadsnakes/nightly https://launchpad.net/~deadsnakes/+archive/ubuntu/nightly
 More info: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
Press [ENTER] to continue or Ctrl-c to cancel adding it.
```
と表示された時にはEnterキーを押してください。
```shell
$ sudo apt update
$ sudo apt list python3.*
```
を実行したときに
```shell
python3.10-dbg/focal 3.10.16-1+focal1 amd64
python3.10-dev/focal 3.10.16-1+focal1 amd64
python3.10-distutils/focal 3.10.16-1+focal1 all
python3.10-examples/focal 3.10.16-1+focal1 all
python3.10-full/focal 3.10.16-1+focal1 amd64
python3.10-gdbm-dbg/focal 3.10.16-1+focal1 amd64
python3.10-gdbm/focal 3.10.16-1+focal1 amd64
python3.10-lib2to3/focal 3.10.16-1+focal1 all
python3.10-minimal/focal 3.10.16-1+focal1 amd64
python3.10-tk-dbg/focal 3.10.16-1+focal1 amd64
python3.10-tk/focal 3.10.16-1+focal1 amd64
python3.10-venv/focal 3.10.16-1+focal1 amd64
python3.10/focal 3.10.16-1+focal1 amd64
```
とPython3.10がインストール可能であることを確認できれば
```shell
sudo apt install -y python3.10 python3.10-venv
```
でPython3.10と仮想環境をインストールします。

# GPUのCompute CapabilityとPyTourchのバージョン
ここで、GPUのCompute CapabilityとPyTourchのバージョンについて解説します。

**Compute Capability**とは、NVIDIAのCUDAプラットフォームにおいて、GPUの機能やアーキテクチャのバージョンを示す指標となります。Compute Capabilityは[cuda-gpus](https://developer.nvidia.com/cuda-gpus)で確認することができ、今回使用している「NVIDIA Tesla K20」のCompute Capabilityは`3.5`になります。

PyTourchはNVIDIAのGPUを使用するため、**Compute Capability**のバージョンとの兼ね合いが非常に重要となります。[関係表](https://github.com/moi90/pytorch_compute_capabilities/blob/main/table.md)で確認すると、`3.5`に対応している最新のバージョンは`pytorch-1.12.1-py3.10_cuda10.2_cudnn7.6.5_0`であり、CUDAのバージョンは`10.2`までです。しかし、今回インストールしているCUDAのバージョンは`11.4`であるためバージョンが合致しません。

以上より、`CUDA11.4`に対応しつつ、`Compute Capability 3.5`にも対応しているPyTourchを探す必要があります。

探してみると、stable-diffusion-webuiのレポジトリ内のDiscussionで[非常に興味深い投稿](https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/13286)がありました。以下に引用します。

> So everywhere I've seen in discussion it is impossible to run stable diffusion in Kepler GPUs except K80 because it supports CUDA compute capability 3.7. Main limitation to run it on CUDA 3.5 is that started pytorch packages come compiled without support for it, you can check it with:
> ```python
> import torch
> torch.cuda.get_arch_list()
> ```
> But what if we compile torch with support for CUDA 3.5 support? Or even better, use precompiled torch from https://github.com/nelson-liu/pytorch-manylinux-binaries.

上記の内容から、[pytorch-manylinux-binaries](https://github.com/nelson-liu/pytorch-manylinux-binaries)に`CUDA11.4`に対応しつつ、`Compute Capability 3.5`にも対応しているPyTourchがあるらしいため、確認すると`PyTorch v1.12.1`に`torch-1.12.1+cu113-cp310-cp310-linux_x86_64.whl`がありました。今回はこちらのバージョンを使用します。（cu113で`CUDA11.3`用ではありますが、どうやら`CUDA11.4`と互換性があるため、こちらを使用します）

# PyTourchのインストールとテスト

ここで、先程の`PyTorch v1.12.1`が`CUDA11.4`と`Compute Capability 3.5`が対応しているか確認をします。
適当なフォルダで
```shell
$ python3.10 -m venv .venv
$ source .venv/bin/activate
$ pip install wheel
```
とPython3.10の仮想環境を作成します。
```shell
$ wget https://github.com/nelson-liu/pytorch-manylinux-binaries/releases/download/v1.12.1/torch-1.12.1+cu113-cp310-cp310-linux_x86_64.whl
$ pip install torch-1.12.1+cu113-cp310-cp310-linux_x86_64.whl
```
でPyTorchをインストールします。最後に
```shell
$ python
>>> import torch
>>> print(torch.__version__)
1.12.1+cu113
>>> print(torch.cuda.is_available())
True
>>> print(torch.cuda.device_count())
1
>>> print(torch.cuda.get_device_name())
Tesla K20c
>>> print(torch.cuda.get_device_capability())
(3, 5)
>>> print(torch.cuda.get_arch_list())
['sm_35', 'sm_37', 'sm_50', 'sm_60', 'sm_70', 'sm_75', 'sm_80', 'sm_86']
```
とPyTourchがGPUを認識しており、かつarch_listに「sm_35」が含まれているため、使用可能なことが分かります。

# Stable Diffusionのダウンロードと依存関係を考えたライブラリのインストール

ここからStable Diffusionをダウンロードし、依存関係を考えつつライブラリのインストールをしていきます。
先程の投稿の方はコミットIDが`commit c9c8485bc1e8720aba70f029d25cba1c4abf2b5c`のバージョンを使用しているため、今回は同じものを使用します。
```shell
$ wget https://github.com/AUTOMATIC1111/stable-diffusion-webui/releases/tag/v1.5.2
$ tar -zxvf v1.5.2.tar.gz
$ cd stable-diffusion-webui-1.5.2
$ python3.10 -m venv .venv
$ source .venv/bin/activate
$ pip install --upgrade pip
$ pip install wheel
$ pip install torch-1.12.1+cu113-cp310-cp310-linux_x86_64.whl
```
これで、Stable DiffusionとPyTourchのインストールは完了です。ここから、`torch-1.12.1+cu113`に対応したライブラリをインストールしていきます。
PyTourchに依存関係を持ちそうなライブラリは`pip install *** --no-deps`で本体のみインストールし、`pip check`で依存関係が壊れてないか、何が関係しているかを探りつつインストールを進めました。
最終的なバージョンは、以下の通りです。
```text
absl-py                   2.1.0
accelerate                1.2.1
addict                    2.4.0
aenum                     3.1.15
aiofiles                  24.1.0
aiohappyeyeballs          2.4.4
aiohttp                   3.11.11
aiosignal                 1.3.2
altair                    5.5.0
annotated-types           0.7.0
antlr4-python3-runtime    4.9.3
anyio                     4.7.0
async-timeout             5.0.1
attrs                     24.3.0
basicsr                   1.4.2
blendmodes                2024.1.1
certifi                   2024.12.14
charset-normalizer        3.4.1
clean-fid                 0.1.35
click                     8.1.8
colorama                  0.4.6
contourpy                 1.3.1
cycler                    0.12.1
einops                    0.8.0
exceptiongroup            1.2.2
facexlib                  0.3.0
fastapi                   0.115.6
ffmpy                     0.5.0
filelock                  3.16.1
filterpy                  1.4.5
fonttools                 4.55.3
frozenlist                1.5.0
fsspec                    2024.12.0
ftfy                      6.3.1
future                    1.0.0
gfpgan                    1.3.8
gitdb                     4.0.11
GitPython                 3.1.43
gradio                    3.32.0
gradio_client             1.5.2
grpcio                    1.68.1
h11                       0.14.0
httpcore                  1.0.7
httpx                     0.28.1
huggingface-hub           0.27.0
idna                      3.10
imageio                   2.36.1
inflection                0.5.1
Jinja2                    3.1.5
jsonmerge                 1.9.2
jsonschema                4.23.0
jsonschema-specifications 2024.10.1
kiwisolver                1.4.8
kornia                    0.7.4
kornia_rs                 0.1.7
lark                      1.2.2
lazy_loader               0.4
lightning-utilities       0.11.9
linkify-it-py             2.0.3
llvmlite                  0.43.0
lmdb                      1.5.1
Markdown                  3.7
markdown-it-py            2.2.0
MarkupSafe                3.0.2
matplotlib                3.10.0
mdit-py-plugins           0.3.3
mdurl                     0.1.2
multidict                 6.1.0
narwhals                  1.19.1
networkx                  3.4.2
numba                     0.60.0
numpy                     1.26.4
omegaconf                 2.3.0
open_clip_torch           2.29.0
opencv-python             4.10.0.84
orjson                    3.10.12
packaging                 24.2
pandas                    2.2.3
piexif                    1.1.3
pillow                    10.4.0
pip                       24.3.1
platformdirs              4.3.6
pretty-errors             1.2.25
propcache                 0.2.1
protobuf                  5.29.2
psutil                    6.1.1
pydantic                  2.10.4
pydantic_core             2.27.2
pydub                     0.25.1
Pygments                  2.18.0
pyparsing                 3.2.0
python-dateutil           2.9.0.post0
python-multipart          0.0.20
pytorch-lightning         2.1.4
pytz                      2024.2
PyYAML                    6.0.2
realesrgan                0.3.0
referencing               0.35.1
regex                     2024.11.6
requests                  2.32.3
resize-right              0.0.2
rpds-py                   0.22.3
safetensors               0.4.5
scikit-image              0.25.0
scipy                     1.14.1
semantic-version          2.10.0
setuptools                65.5.0
six                       1.17.0
smmap                     5.0.1
sniffio                   1.3.1
starlette                 0.41.3
tb-nightly                2.19.0a20241229
tensorboard-data-server   0.7.2
tifffile                  2024.12.12
timm                      1.0.12
tokenizers                0.13.3
tomesd                    0.1.3
tomli                     2.2.1
torch                     1.12.1+cu113
torchaudio                0.12.1+cu113
torchdiffeq               0.2.5
torchmetrics              1.4.0
torchsde                  0.2.6
torchvision               0.13.1+cu113
tqdm                      4.67.1
trampoline                0.1.2
transformers              4.25.1
typing_extensions         4.12.2
tzdata                    2024.2
uc-micro-py               1.0.3
urllib3                   2.3.0
uvicorn                   0.34.0
wcwidth                   0.2.13
websockets                14.1
Werkzeug                  3.1.3
wheel                     0.45.1
yapf                      0.43.0
yarl                      1.18.3
```

全てのライブラリをインストール出来れば
```shell
$ bash ./webui.sh --listen
```
で起動し、他のマシンからアクセスすれば
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/835335/f6f73755-cd6c-f118-de9e-372f9ce8cc47.png)
と無事起動できていることが分かります。

# 課題
問題なくStable Diffusionが起動し、また「-–medvram」などを加えることで画像の生成も出来ていることは確認が出来ました。しかしながら、一つ問題が残っています。

それは、**xformers**が使えないということです。

今回のバージョンに合致するxformersが見つからなかったため、メモリなどの最適化が出来ていません。恐らく、[PyPI](https://pypi.org/project/xformers/#history)に載っていない`0.0.14`もしくは`0.0.15`が対応しているのではないかと睨んでいますが、Githubにも載っていないためお手上げ状態です。

今後、もし見つかればxformersのインストール方法も記載しようと考えています。

# 余談

以前

https://qiita.com/ll_Roki/items/fff2b3030d1e21633ee8

で紹介した、Radeonによる画像生成と速度を比較すると、今回の方が圧倒的に早いですね。

世代的には圧倒的にRadeon RX570（大体GTX1060と同世代）が上ですが、もともとデータセンター向けに開発されていたモデルだからか、NVIDIA Tesla K20の方が早かったです。

**税込み2480円**でこれは優秀と言っても良いのではないでしょうか。

# 最後に

今回は、Keplerアーキテクチャ世代の「NVIDIA Tesla K20」で、Stable Diffusionを使用する方法について解説をしました。皆さんの参考になりましたら幸いです。

# 参考文献
https://qiita.com/tf63/items/0c6da72fe749319423b4

https://qiita.com/kyad/items/cd2deb0e2086d12e4bf3

https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/13286