端の知識の備忘録

技術メモになりきれない、なにものか達の供養先

【2023年最新版】 鯖落ちGPUを使った安価な機械学習用マシンの作り方

続編書きました:

hashicco.hatenablog.com

背景

このブログを始めた2020年頃に、NVIDIA Tesla K40mを使った安価な機械学習GPUマシンを紹介した。

hashicco.hatenablog.com

その後このマシンは勉強用に色々と活用していたのだが、2020年時点でもアーキテクチャが Kepler (Compute Capability 3.5) と古く、何より計算スピードが遅すぎてKaggleなどでの活用が難しい問題があり、 結局Google Colab ProやKaggle Notebookをメインで使っていた。

更に、最近はRTX4090をメインマシンに導入したこともあり、このK40mマシンの出番はほぼなくなってしまった。

で、先日メインマシンのCPUを7950X3Dに変更したことで、AM4のCPUとマザボ、64GBのDDR4メモリなど、ほぼPC一式分のパーツが余剰となった。 売ってお金にすればよいというのに自作趣味の悪いところが出てしまい、サブマシンの更新をしたい欲が沸々と湧き上がる。

とはいえ先ほど言ったようにK40mはもう古いしなぁ……などと思いながら eBayを物色していたところ(これが良くなかった)、 Keplerより2世代新しいサーバー用GPUである Tesla P40が$200程度で売られているのを見つけてしまった。

https://www.ebay.com/itm/374377271140www.ebay.com

ちょっと調べてみると、VRAMはRTX3090/4090と同じく24GB搭載しており、FP32演算性能としてはKaggleやGoogle Colabでも使えるP100と同等と、サブマシンには適当な性能に思える。一方でP100と異なり半精度 (FP16) の演算はHW的に最適化されていないようで、近年当たり前に使われるMixed Precision 利用時の性能には不安が残るものの、このキワモノ感も検証欲をそそられる。

ということで、詳しいことは買ってから考える精神でNVIDIA Tesla P40をポチって令和最新版の格安?機械学習用マシンを組んでみたというお話。

簡単な性能検証や気になっていたMixed Precision利用時の挙動を確認してみたので興味がある方は下へどうぞ。

まとめ

  • P40はお手頃価格の機械学習用24GB VRAM GPUになるポテンシャルあり。3万で買えるGPUとしては破格の性能だと思う。

    • K40m同様、 サーバー用GPUなので普通のGPUとは異なる工夫 (具体的にはPassive冷却や映像出力がないことに対する対応) が必要になる。 試行錯誤や失敗ウェルカムなパワーユーザーにしかお勧めできません。 また、本ブログの内容で損失を被っても私は責任を持ちません。
  • P100と比較すると、 P40はVRAM容量では勝るが、 VRAM帯域やFP16への対応などで劣る。 中古価格では1~2万程度の価格差でP100を買えるようなので、どっちを選ぶかは悩ましい。

    • 5万出せるならRTX3060 12GBを選ぶほうが製品寿命やワッパ、他用途への流用やリセール的に良い気もするのでさらに悩ましい。 その点色々割り切って安いP40を選ぶというのはありかもしれない
    • Pascalアーキテクチャももう4~5世代、7年前の製品なので、 CUDAサポートの打ち切りもいずれ来ることを考慮して購入検討すべき。
  • 懸念であった Mixed Precision 利用時の挙動であるが、確かにT4 GPUのような Mixed Precision利用を想定されているGPU(約80%高速化)に比べてトレーニング時間の削減効果は少なく、 MobileNetトレーニング時に20%程度しか計算時間を改善できなかった

    • ということで、簡易的な計測だがFP32 トレーニングではP40はT4 (Google Colab) よりも2割ほど高速だが、 Mixed Precision トレーニングではT4よりも2割程度低速になるという結果が得られた。
    • しかし、 VRAM使用量の削減効果は大きいので、 P40でもMixed Precision を使う価値はある。
  • 今回はeBayの中国セラーから送料込$207で購入したが、 状態は良好。 注文から10日程度で受け取れた。

    • 電源供給に必要なPCIe 8pin x2→ EPS 8pin ケーブルもNVIDIA純正?らしきケーブルがついてきた
  • MSIのB550マザー+5800X3Dの構成にP40と映像出力用の適当なGPUを刺してUbuntuをセットアップできた。

    • このマザーではグラフィック出力のないGPUの接続があまり考慮されていないようで、デフォルト設定ではUEFI POSTのVGAチェックでコケてしまい大分詰まった。 結局UEFIの設定をいろいろいじったらうまく行ったので、ここは後述する。
  • パーツは流用したから実質タダみたいなもの……という冗談はさておき、 今P40を採用しつつコスパ重視すれば、13万くらいでそこそこの機械学習用マシンを組めると思います。

    • 内訳はGPU: P40(3万)、CPU: 5900X(4.5万)、MB: B550(1.5万)、Mem: DDR4 64GB(2.5万)、 SSD: 1TB(0.7万)、電源: 750W (0.8万)。 ケースなしが許容され冷却用のファンとか細かいパーツはそこらに転がっている逸般の誤家庭 (死語) を想定

なにより、 おうちにサーバー用GPUのTeslaがあるのってロマンだよね! というところが一番大きなモチベだったりするので深く考えずに買っちゃいましたが、思ったよりも使える可能性を感じました。

昨今のLLMやDiffusion系生成モデルのようなVRAM食い機械学習モデルを動かす際にも使えるかもなので、その辺は今後使いながら検証していきたいと思います。とりあえず今回は一通りのセットアップと簡易的なベンチマークまでを記しておくつもり。

P40について

P40の基本スペックは

NVIDIA Tesla P40 Specs | TechPowerUp GPU Database

を参考に次の通りです。

  • Compute Capability: 6.1
  • CUDA cores: 3840
  • VRAM: 24GB GDDR5, 346GB/s
  • FP32演算性能: 12TFLOPS
  • FP16演算性能: 183.7 GFLOPS (1:64)
  • 消費電力: 250W

コンシューマ製品でいうと大体GTX1080 Tiのメモリ多い版と認識しておけば良いかもしれません。

また、ご覧の通りFP16の性能はFP32比で1/64と大きく削減されている(ちなみにP100は 2:1)。P40発売時の記事を見るとトレーニング用GPUとして発表されているものの、発売された2017年頃はまだTensorFlowやPyTorch(Chainer)などのフレームワークでも自動半精度やAuto Mixed Precisionのサポートもなかったであろうから、あまり重視されなかったのであろう。

届いたP40はちゃんとクリーニングされているのか保守在庫だったのかわかりませんが非常にきれい。 バックプレート側に"IASER"というメーカー名っぽいシールが新しく貼られているのですが、軽くググっても何を意味するのか分からず。 もしかするとサーバー用GPUのリファービッシュを販売している中国メーカーなのかもしれません。

P40は電源供給にEPS 8pin(マザボに指すCPU用の12Vコネクタと同じ)を使うのですが、PCIe 8pin x2からの変換ケーブルもNVIDIAのロゴの入ったタグの付いた純正?らしきものがついてきました。

K40mとの比較写真。Pascal世代のカードのデザインはNVIDIAぽさがあって良き。

P40はパッシブ冷却なので、前回作成したダンボールで作ったハウジングを取り付けたファンと一緒に使います。

組み立て

メインのパーツは前世代のPCから流用します。 また、我が家では床に直置きだと取り回しに問題があることが前回の経験からわかっていたので、今回は少しお金はもったいないですが所謂ベンチ台を購入してその上に組立しました。

  • MB: MSI MPG B550 Gaming Plus
  • CPU: Ryzen75800X3D
  • CPU cooler: Deep Cool AK400
  • Mem: DDR4 3200MHz 64GB (Micron, ADATA2枚ずつ混載)
  • SSD: MX500 1TB SATA
  • GPU (Graphics): Quadro K600
  • GPU (Compute): Tesla P40
  • PSU: Corsair RM1000
  • Case: 2WAY ベンチテーブル SMZ-2WBT-ATX

ゲームしないのに5800X3Dはもったいないので、 これだけは売ってしまって5900Xに買い替えたいとは思っています。

ちなみにベンチ台は13000円もしたのですが、正直ただの金属フレームです。安価に作る目的に反してちょっと高すぎる印象は受けますが、工作精度はそれなりに高くねじ穴ずれなどはなかったのでまあ納得して使っています。

Amazon.co.jp: 【長尾製作所×シミラボ】 2WAY ベンチテーブル SMZ-2WBT-ATX : ホーム&キッチン

出来上がりはこんな感じ。

UEFU設定、Ubuntuインストール

UEFI設定はだいぶ苦戦しました。 最初にP40を1つ目のx16に、 K600を2つ目のx16に刺したところ、 "VGA" のPOSTチェックLEDが点灯してしまいUEFI画面が映らず。

K600だけを接続したところちゃんとUEFIが映ったので、色々いじって試したところ次の設定でうまく行きました。 必要十分条件であるとは検証できていませんが、とりあえず私の環境では動いた条件として認識ください。

  • Above 4G memory/Crypto Currency mining: Enabled
  • Re-Size BAR Support: Enabled
  • VGA Detection: False
  • Full Screen Logo Display: Disabled

このUEFI設定でP40を1つ目のx16に、K600を2つ目のx16を刺して起動を確認できました。

Ubuntuは22.04を利用。 適当なUSBメモリにEtcherでISOを焼き、 普通にインストールを実行。

その後、openssh-serverのインストール固定IPアドレス設定CUDAインストールをリンク先を参考に行い、ベンチを取りました。

簡易ベンチマーク

TensorFlow2からの見え方

ベンチマークではないですが、一応。

>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 5659398530349240384
xla_global_id: -1
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 23176478720
locality {
  bus_id: 1
  links {
  }
}
incarnation: 13990392878040664411
physical_device_desc: "device: 0, name: Tesla P40, pci bus id: 0000:2b:00.0, compute capability: 6.1"
xla_global_id: 416903419
]

ai-benchmark

この記事でRTX4090の性能を測るときにも紹介した、機械学習性能を簡易的に測れるPythonパッケージ。出力全文は最後に載せます。

>>> from ai_benchmark import AIBenchmark
>>> benchmark = AIBenchmark()

>>   AI-Benchmark-v.0.1.2
>>   Let the AI Games begin..

>>> results = benchmark.run()

*  TF Version: 2.12.0
*  Platform: Linux-5.19.0-38-generic-x86_64-with-glibc2.35
*  CPU: N/A
*  CPU RAM: 63 GB
*  GPU/0: Tesla P40
*  GPU RAM: 21.6 GB
*  CUDA Version: 11.8
*  CUDA Build: V11.8.89

~省略~

Device Inference Score: 11065
Device Training Score: 10797
Device AI Score: 21862

スコア的にはもちろんRTX4090には及ばず。公式のランキングを見ると一番近いスコアはRTX2070ですが、P40はVRAMが24GBもあるので実行できるモデルのサイズは段違い。しかもたった3万円であることを考えれば十二分なスコアではないだろうか。

MobileNetによるcats_and_dogs分類モデル

ここの記事で紹介した、TensorFlow2のチュートリアルで扱われているMobileNet V2でcats_and_dogsデータセットの画像分類モデルをトレーニングする速度を測りました。

比較対象がいないとわかりにくいと思いますので、Google ColabのT4 アクセラレータを有効化したインスタンスでも同様のコードを実行しました。もちろんCPUやディスクの性能は大きく違うので、対等な比較でないことを念頭に参考程度に見てください。

画像サイズを2種類(160x160, 512x512)、Mixed Precision有効/無効の4パターンで計測。2エポック目以降の実行時間(s/epoch)で比較します。

  • 160x160
P40 T4(Colab)
Mixed無効 5.78s 7.61s
有効 5.73s 6.84s
倍率 x1.01 x1.11
  • 512x512
P40 T4(Colab)
Mixed無効 45.71s 54.84s
有効 38.61s 30.47s
倍率 x1.18 x1.79

小さな画像サイズではP40のほうがT4よりも精度に関わらず速い結果に(おそらくColabのCPUかIO性能がリミットになっている?)。一方画像サイズが大きくなると、Mixed Precision無効化ではP40のほうが速いが、有効化ではT4よりも遅くなるという結果が得られた。

P40はあまりMixed Precisionによる演算速度向上の効果が得られにくいということがわかる。とは言え、やはり3万円でT4並の性能でVRAM 24GBのグラボが手に入るのは魅力的だと思う。

Mixed Precisionを利用したときの最大バッチサイズ

最後に、P40におけるMixed Precisionがどのように利用VRAM量に影響を与えるかを確かめるため、先程のMobileNet V2のモデルの入力を512x512にしたときにOOMを吐かずに動く最大バッチサイズを探ってみました。

  • Mixed Precision無効: max_bs=68
  • Mixed Precision無効: max_bs=112

結果、Mixed Precisionを有効にすることで、倍とまではいかないものの1.6倍以上のバッチサイズを設定できることがわかった。大きなモデルを利用するときなどには、P40であってもMixed Precisionを有効にするのが良さそうである。

ai-benchmark全文

>>> from ai_benchmark import AIBenchmark
>>> benchmark = AIBenchmark()

>>   AI-Benchmark-v.0.1.2
>>   Let the AI Games begin..

>>> results = benchmark.run()

*  TF Version: 2.12.0
*  Platform: Linux-5.19.0-38-generic-x86_64-with-glibc2.35
*  CPU: N/A
*  CPU RAM: 63 GB
*  GPU/0: Tesla P40
*  GPU RAM: 21.6 GB
*  CUDA Version: 11.8
*  CUDA Build: V11.8.89

The benchmark is running...
The tests might take up to 20 minutes
Please don't interrupt the script

1/19. MobileNet-V2

1.1 - inference | batch=50, size=224x224: 63.0 ± 0.8 ms
1.2 - training  | batch=50, size=224x224: 191.9 ± 0.5 ms

2/19. Inception-V3

2.1 - inference | batch=20, size=346x346: 62.0 ± 1.1 ms
2.2 - training  | batch=20, size=346x346: 255.4 ± 0.8 ms

3/19. Inception-V4

3.1 - inference | batch=10, size=346x346: 61.9 ± 1.0 ms
3.2 - training  | batch=10, size=346x346: 255.3 ± 0.6 ms

4/19. Inception-ResNet-V2

4.1 - inference | batch=10, size=346x346: 84.6 ± 0.7 ms
4.2 - training  | batch=8, size=346x346: 282.0 ± 0.6 ms

5/19. ResNet-V2-50

5.1 - inference | batch=10, size=346x346: 45.0 ± 0.6 ms
5.2 - training  | batch=10, size=346x346: 166.2 ± 0.4 ms

6/19. ResNet-V2-152

6.1 - inference | batch=10, size=256x256: 60.0 ± 0.7 ms
6.2 - training  | batch=10, size=256x256: 234.7 ± 0.6 ms

7/19. VGG-16

7.1 - inference | batch=20, size=224x224: 91.0 ± 1.0 ms
7.2 - training  | batch=2, size=224x224: 185 ± 1 ms

8/19. SRCNN 9-5-5

8.1 - inference | batch=10, size=512x512: 87.7 ± 3.3 ms
8.2 - inference | batch=1, size=1536x1536: 74.4 ± 2.1 ms
8.3 - training  | batch=10, size=512x512: 247 ± 3 ms

9/19. VGG-19 Super-Res

9.1 - inference | batch=10, size=256x256: 67.7 ± 0.5 ms
9.2 - inference | batch=1, size=1024x1024: 103.0 ± 0.7 ms
9.3 - training  | batch=10, size=224x224: 251.2 ± 0.9 ms

10/19. ResNet-SRGAN

10.1 - inference | batch=10, size=512x512: 116 ± 1 ms
10.2 - inference | batch=1, size=1536x1536: 105.7 ± 0.8 ms
10.3 - training  | batch=5, size=512x512: 198.5 ± 0.7 ms

11/19. ResNet-DPED

11.1 - inference | batch=10, size=256x256: 148.6 ± 0.5 ms
11.2 - inference | batch=1, size=1024x1024: 250.8 ± 0.4 ms
11.3 - training  | batch=15, size=128x128: 265.1 ± 0.5 ms

12/19. U-Net

12.1 - inference | batch=4, size=512x512: 262 ± 2 ms
12.2 - inference | batch=1, size=1024x1024: 262 ± 1 ms
12.3 - training  | batch=4, size=256x256: 304.0 ± 0.3 ms

13/19. Nvidia-SPADE

13.1 - inference | batch=5, size=128x128: 120.4 ± 0.6 ms
13.2 - training  | batch=1, size=128x128: 214.0 ± 0.0 ms

14/19. ICNet

14.1 - inference | batch=5, size=1024x1536: 178 ± 4 ms
14.2 - training  | batch=10, size=1024x1536: 507 ± 12 ms

15/19. PSPNet

15.1 - inference | batch=5, size=720x720: 513 ± 1 ms
15.2 - training  | batch=1, size=512x512: 207 ± 2 ms

16/19. DeepLab

16.1 - inference | batch=2, size=512x512: 142.6 ± 0.5 ms
16.2 - training  | batch=1, size=384x384: 162.8 ± 0.4 ms

17/19. Pixel-RNN

17.1 - inference | batch=50, size=64x64: 339 ± 9 ms
17.2 - training  | batch=10, size=64x64: 1055 ± 33 ms

18/19. LSTM-Sentiment

18.1 - inference | batch=100, size=1024x300: 480 ± 12 ms
18.2 - training  | batch=10, size=1024x300: 846 ± 19 ms

19/19. GNMT-Translation

19.1 - inference | batch=1, size=1x20: 174 ± 3 ms

Device Inference Score: 11065
Device Training Score: 10797
Device AI Score: 21862