RTX3090Tiで機械学習マシンを自作しtensorflowを動かすまで

<H1>きっかけ</H1>

ずっとGoogle Colabでやってました。Proが出来てからはProで。でも2022年9月末の従量課金制になってからは実質追い出されたも同然で、Proでたった月1000円でP100を24時間1か月回しっぱなしなんてことはもう絶対にできない状況になりました。
まぁでもいままで出来ていたのが出血大サービスだったわけで、V100だと1000円なんて半日ちょっとで使い切る現在の状態のほうが本来の価格なのでしょう。

だけど課金してColabのV100 A100を使うとなると、回しっぱなしだと1月でV100で50000円、A100だと100000円くらいかかるわけで、それを払ったとしても24時間で切られることもデータが毎回消えてしまうため(ImageNetとかの）大きいデータが使えないのは相変わらずなので、なんか仮想通貨が安くなったりRTX40XXシリーズが出てRTX30XXが安くなってるというので頑張って自前のマシンを作ってみようということになりました。

<H1>　購入した部品 </H1>

| パーツ | 製品名 | 価格 |
|:-:|:-:|:-:|
| CPU  |i7 12700無印   |  51000 |
|  GPU |MSI GeForce RTX 3090 Ti SUPRIM X 24G |  189800 |
|  GPU延長保証 |   |9900   |
|マザー   |PRIME H670-PLUS D4   | 14979  |
|電源   |CORSAIR HX1200 | 33980  |
| HDD | シーゲイト8TB  |15480   |
|ケース |Antec DF700 FLUX   | 10980  |
| メモリ  | DDR4 16GB x2  | 13544  |
| SDD  | M.2 NVMe 1TB  |13085   |
| CPUファン  | DEEPCOOL AK400  | 3474  |
| ケースファン  | darkFlash C6 3in1| 2790  |
| USBメモリ  | 64GB x2 | 1540  |
| 計  |   | 360552  |

RTX3090を選んだのはもちろんVRAMサイズが理由です。バッチサイズを少しでも大きく取りたい。24GBはA100に比べれば落ちますが、ColabのV100は16GBなのでそれよりは大きいですし個人でなんとか買える価格の範囲ではこれが最大でした。
Tiになってしまったのはたまたま安かったのと成り行きですが、性能差は僅かですので消費電力の低い無印のほうがよかったような気はします。同じ学習をさせたときに消費電力がどれくらい違うのかは知る由もありませんが。
GPUだけは1年保証は怖いので延長保証をつけてみました。気休めかもしれませんが。玄人志向とかGigabyteとかだと保証が長いそうです。あとショップによっていろいろな延長保証があるので自分のような心配な人は調べてみたら少しは不安感が軽減されるかしれません。実際壊れたらちゃんと延長保証が役に立つかはわかりませんが、それを知らないで済むに越したことはありませんね。

USBメモリはインストール用に買いました。どうせミスしてやり直しとか発生するだろうからwinとubuntuと同時に作っておけるように念のため2個。安いし。

GPUの冷却がとにかく問題ということだけはネットで調べてみるとわかっていたのでケースファン全面x3 上面x3 内部x1 背面x1の8基としました。

いままでも適当な安いマシンを作ったことはありますが、こんな高いマシンを作るのは初めてのことです。

![IMG_6416_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/0d64d7df-75e3-2b6f-600a-20f869ae5012.jpeg)
やってきたパーツ。

![IMG_6417_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/105f2067-ad45-f2a2-608d-c60810442f37.jpeg)

MSI の GeForce RTX 3090 Ti SUPRIM X 24G。ごつい箱です。ケースの次にでかい。

![IMG_6420_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/55162946-ae70-7d2b-abc4-6c698d53a578.jpeg)

裏。自分は手は結構大きいほうですが、それでこのサイズ。そして重い。

![IMG_6421_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/5b629ec6-7694-444f-8202-c8c135a95c79.jpeg)
表。

<H1> 組み立て </H1>

組み立てはそれなりに苦労しました。まずファン。アドレザブルRGBとかいう光るファンの配線がやたらややこしくてどこがどこにつながるべきなのか調べるのに手間取りました。機械学習マシンは光る必要は全くないのですが、最近のPCケースは光るファンがついていない方が珍しいくらいみたいで、せっかくあるのにつながないのは負けた気もするので調べて何とかつなぎました。ファンのケーブルがすごくて初めはワーッとパニックになったのですが、頭を冷やして光らなくても別にいいや～くらいに考えると光るためのケーブル以外は別に昔からのPCと変わらないのでとにかく従来からあるファン用のピンだけは繋ごうというふうに切り替えたら気が楽になって出来ました。

そして電源。余裕をもって1200Wにしたのですが奥行300mmでケースの電源奥行きが最大305mmで数値上は大丈夫だったのですが、電源の後ろにケーブルを差さなくてはならないので当然5㎜では無理で、結局電源の後ろにあったHDD固定用金具を外しました。

グラボがとにかくでかいので、グラボを差してからだとできないことがいっぱい出てきます。SATAのケーブルがそれでした。更にこのケース、GPUの下にGPU用？の内部ファンがついていてこれのせいでなんとかアクセスできそうだったSATAプラグ２つも触れられない位置に。あまりグラボの抜き差しはしたくないので、SATAをあとから増設したいと考えてる人はとにかく先に全部のSATAプラグにケーブルだけ差しておくといいんじゃないと思います。

![IMG_6422_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/7d76f295-eedc-3700-01c7-931119e4aef6.jpeg)
取りあえずグラボ抜きで起動。12700無印なんでマザポのHDMI出力が生きています。何があるかわからないのでエマージェンシー用に一応Fを選ばないでおきました。BIOS設定画面はなんとか表示されまずは一安心。

![IMG_6423_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/77621d28-b75e-520e-2102-64449118df70.jpeg)
そして RTX3090Tiを差しての起動。はじめ補助電源の取り方がわからず戸惑いましたが問題なく起動しました。
補助電源はTiは16Pin１つですが電源が対応していないのでグラボに8Pin3つの3つ又ケーブルが付属しています。これを電源につなぐわけですが、8Pinのケーブルがどれだかわからず追加で買わなきゃいけないのか？と焦りましたが、PCIeと書いてある6pin+2Pinのケーブルをくっつけて8PinにしてつなぐのでOKでした。ちなみにCPUと書いてあるちょうど8Pinのケーブルもありますが、これは使っちゃだめです。というかダメでした。こんなミスするのは自分だけかもしれませんが、Pin数が同じでささってしまうので注意です。
![IMG_6434_1024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959912/b65c5bba-08eb-9a88-c6a7-78294aca3a82.jpeg)

さてOSを入れるわけですが、機械学習的にはubuntuだけでいいのですけど折角のグラボなので一応WinもいれとこうということでまずはWin11を入れubuntuのデュアルブートにします。
Win11でNVidiaのドライバを入れ、3DMarkを走らせたところ Time Spyで 21000くらいでした。ネット記事でみるくらいの数値になってるのでグラボはちゃんと動いているということのようです。

あと、上面用に買った３連ファンですが、３つで2000円台でアドレザブルで安いなと思ったら安いなりのことがあって、なんかカリカリという小さな妙に耳障りな音がするので結局外して分解した古いPCから取った地味な光らない120mm x3に置き換えました。静かになりました。

<H1>Tensorflowのインストール</H1>

ubuntuはすんなり入り、Tensorflowを入れていくわけですがこれが一番苦労しました。
とにかく動く環境がなんだかわからない。RTX3090は出てもう結構に時間たってるわけなのですが、それでも十分新しすぎるらしく動くためのcudatoolkit,cudnn,tensorflowの組み合わせがさっぱりわからない。組み合わせが正しくてもRTX3090で動かなくては意味がないし、あまりに新しいtensorflowを入れてしまうとできたweightを実装する環境の方が対応できなくては作る意味がない。それを考えると最新のRTX4090を清水の舞台から～で買おうした瞬間もありましたがやめておいてよかったのかもしれません。

<H1>Anaconda</H1>
Dockerでやるやり方が主流なのかもしれませんが、いままでAnacondaでやってきた流れでAnacondaを使いたいと思いました。
それで色々試したわけですが、失敗例をたくさん書いても仕方がないので成功したパターンを書きます。
つまるところanacondaの方でいい具合にcudatoolkit,cudnn,tensorflowを組み合わせたパッケージを丸っと用意してくれてるということらしいです。ありがたや。

~~~
conda search tensorflow
~~~
とすると
~~~
tensorflow 2.10.0 eigen_py37ha43bb76_0 pkgs/main
tensorflow 2.10.0 eigen_py38h77fcdc8_0 pkgs/main
tensorflow 2.10.0 eigen_py39he2aad1f_0 pkgs/main
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.10.0 mkl_py310h24f4fea_0 pkgs/main
tensorflow 2.10.0 mkl_py37h5d113c5_0 pkgs/main
tensorflow 2.10.0 mkl_py38hd2379f1_0 pkgs/main
tensorflow 2.10.0 mkl_py39hdc5b6f4_0 pkgs/main
~~~
こんな感じのがいっぱい出てきます。これの2.10.0の部分がtensorflowのバージョンなので好きなバージョンを選び、gpu_pyXXXXXXXX_0 というのがgpu対応版なのでpythonのバージョンを好みで選べばいいみたいです。

~~~
conda create -n tf210
conda activate tf210
conda install tensorflow=2.10.0=gpu_py37h84cb581_0
~~~
これでもうcudatoolkit,cudnnもいい具合に組み合わせくれてtensorflowが動きます。kerasはtensorflowのバージョンによっては更にconda install kerasをしなくてはいけない場合もありました。2.10.0では不要でした。

更にnotebookを使いたいので

~~~
conda install jupyter
~~~
jupyter notebookはインストールしなくてもjupyter notebook&で起動するのでいらなそうに思えますがそれだとimport tensorflowが module not foundになってしまいました。仮想環境にjupyterが入っていないので見てる場所が違うということのようです。

~~~
conda install matplotlib
conda install -c conda-forge opencv
conda install Pillow
~~~
更に自分が学習につかうグラフ、画像関係の処理のモジュールをインストールします。最後のPillowはPILのライブラリとしてkerasのload_imgで使うらしいです。このへんは人によって結構違うんじゃないかと思います。

こちら[conda install のみでTensorFlowとGPU環境（CUDA、cuDNN）を構築する](https://qiita.com/ktokey/items/7ee9c112198a6b0b5709)がとても参考になりました。

そしてRTX3090とtensorflowのバージョンの関係ですがなんでも入るわけではありません。ここでRTX30xxシリーズが新しすぎるということが問題になります。

例えばconda search tensorflowのリストにあったtensorflow 2.4.1はcudaが10.1だったため動きませんでした。
それでも一応走らせてみたのですが
2022-11-09 09:57:51.487158: W tensorflow/core/framework/op_kernel.cc:1763] OP_REQUIRES failed at cwise_op_gpu_base.cc:89 : Internal: Failed to load in-memory CUBIN: CUDA_ERROR_NO_BINARY_FOR_GPU: no kernel image is available for execution on the device

あちこちで妙に時間がかかったりとおかしいのですが最終的にfitでこんなエラーが出て学習しませんでした。

2.8.2は動きました。入ったcudatoolkitととchdnnを見ると
cuda 11.3.1
cudnn 8.2.1
となっています。cudaは11以上でないとRTX30xxは動かないみたいです。

ほんとうは1.15も試したかったのですが、2.4.1でも低すぎてダメなくらいだったので動く目はないと考え試しませんでした。1.15でないとweightが実装できない環境があったからなのですが、これは当面のところ諦めるしかなさそうです。
ネットで調べてみるとRTX3090で1.15動かした人の記事が少しは見つかるので引き続きちょこちょこ気にしておくことにします。でも同じ頑張るなら実装環境をtensorflow 2.xにしていく努力をするほうが前向きかもしれません。

<H1>実際の学習1</H1>
なんとかtensorflowが動く環境になってきたところで、実際に学習した結果がどうだったか。

まず自前で256x256の画像から必要な点を検出するresnetを改造したモデルがあったのでそれで試しました。

Total params: 13,179,472
Trainable params: 13,165,200
Non-trainable params: 14,272

パラメータ1300万、weight(hdf5)のサイズで50MBくらいの比較的軽いモデルです。
バッチサイズ2、1epoch=1000で回しました。Colabが従量課金制導入後に作ったモデルなのでColabのほうはT4になってます。

| マシン | GPU | 1stepあたり | 1epochあたり |
|:-:|:-:|:-:|:-:|
|  Colab | T4  |  2s | 2001s=33分 |
| 自作PC  |RTX3090Ti   | 45ms  | 45s=45秒 |

とんでもない速さです。T4の50倍くらい出てます。
このあとバッチサイズを16倍の32にしてみたのですが、
1step 662ms、1epoch 662秒=11分
でした。

そして学習中のGPUの様子をnvidia-smiで見てみると

| Fan | 温度 | 電力 | VRAM |GPU使用率|
|:-:|:-:|:-:|:-:|:-:|
| 32%  | 63C  | 166W / 480W  | 24000MiB / 24564MiB  |13%|

でした。グラボの横あたりのガラスを触るとほんのりあったかいかな？くらいです。GPU使用率が13%しかありません。

<H1>実際の学習2</H1>

次はちょっと重たい512x512のInPainting、DenseNet-121を改造した感じのモデルです。
バッチサイズは1。Colabでは2だとResourceExhaustedErrorが出て死んでしまって1でギリギリ動かしていました。
1epoch=5000で回していました。
Colabの従量課金制導入前でPro契約をしていたころに作ったものなのでColabはP100になってます。体感でP100はT4の2倍～3倍の速さでした。

Total params: 4,101,802
Trainable params: 4,101,802
Non-trainable params: 0

h5サイズで17MB、パラメータ数400万と小さいように見えるのですけど、DenseNetは重いですね。

| マシン | GPU | 1stepあたり | 1epochあたり |
|:-:|:-:|:-:|:-:|
|  Colab | P100  |  455ms | 2259s=38分 |
| 自作PC  |RTX3090Ti   | 234ms  | 1063s=17分 |

だいたい2倍ちょっとくらいでしょうか。もう今では使えないので数値は出せませんが、以前日本でColabのProが使えるようになってしばらく、V100が使えていた時期がありました。そのときの感覚だと、V100はP100の2倍少しくらいの感じだったので、RTX3090≒V100くらいの認識でいいかと思いました。ColabのV100は16GBなので（自分が当たったのが16GBだっただけかもしれませんが）VRAMでは勝ってますので、バッチサイズなどでは少しだけV100より強いと言えるかもしれません。

このモデルの学習中のGPUの様子をnvidia-smiで見てみると

| Fan | 温度 | 電力 | VRAM |GPU使用率|
|:-:|:-:|:-:|:-:|:-:|
| 52%  | 79C  | 311W / 480W  | 23911MiB / 24564MiB  | 52% |

今度は消費電力が一気にあがりました。温度も結構あがってグラボ横のガラスも結構熱いです。触ってられない程ではありませんが。
しかし300Wでもずっとついてるとそれなりに熱を部屋のなかに吐き出しているもので、冬も近いというのに机の周りが暑いくらいです。
でもこれでも使用率52%。100%になったらどうなってしまうのか、恐ろしいです。夏に学習させるのはなかなか大変になりそうです。
温度は90%くらいまでは大丈夫ということでFanも半分しか回ってないみたいなので一応まだ大丈夫なんでしょうが、あまり熱くなるようなら更にファンの増設とか考えないといけないかもしれません。