序章









みなさんは,格安でGPUサーバーが借りられるとして最近流行りの「vast.ai」というサービスをご存じでしょうか?

これは,個人や小規模事業者,マイニング事業者が所有するGPUマシンをP2P的にGPUを貸し出すサービスであり,運営コストが極端に低いため,通常よりも1/2~1/10倍と破格の価格設定となっています。

もちろん,GPUはそれ本体だけではただの火を吹く文鎮であり,何もできないため,このサービスではオマケ程度にCPU・RAMが付属するのですが,ときどきミドルレンジのGPUになぜか256 vCPUや512 vCPUが付属していることがあります。

そこで,vastaiの公式APIを叩き,GPU完全無視でvCPUあたりの単価が安い順に上から契約・クラスター化することにより,圧倒的に破格のHPC環境を作り出してみました。

具体的には,リストの上位N個までを契約すると次のような構成になります。

上位10個: 676 vCPU / 1,146 GB RAM / \\$1.120/hr
上位30個: 1748 vCPU / 4,197 GB RAM / \\$3.142/hr
上位50個 : 4012 vCPU / 8,469 GB RAM / \\$8.293/hr
上位100個: 8272 vCPU / 26,301 GB RAM / \\$21.220/hr
上位200個: 14967 vCPU / 51,809 GB RAM / \\$51.179/hr
上位300個: 20564 vCPU / 69,625 GB RAM / \\$85.973/hr


※もちろん,結果は現在提供されているインスタンスの状況によって変化します。

これに基づくと,vCPUあたりの単価が安いインスタンスを上位10個契約することで,なんと1時間あたり約150円で676 vCPU / 1.1 TB RAM (+ GPU 10個)の圧倒的高コスパな環境が構築できることになります。

コスパ順に並べているため下まで契約するほどコスパは悪化してきますが,それでも上位300個を契約することで,1時間あたり13,000円程度で 20k vCPU / 70 TB RAM (+ GPU 300個以上) というスーパーコンピューター級の環境を利用することが可能です。

もしもAWS/GCPで同じ構成を作った場合には,どんなに低く見積もっても下限は$1,200/hr程度になります。これと比べると,約20倍も安くなっていることになります(もちろん,その代わりにサポートも保証もありませんが)。

実際に私は,高コスパなインスタンスが大量に空いている時間帯を見計らって,

20,450 vCPU
69,237 GB RAM
300 GPU
\\$83.849/hr


というクラスター環境を構築することに成功しました。費用がかさむため短時間ですが,この環境でいろいろと遊んでみたので,備忘録程度に記事を残しておきます。

なお勘の良い方はお気づきかと思いますが,これはいつでも先着一名です。誰かが全く同じことを考えて,vCPU単価の安い順で大量に契約していればコスパは急激に悪化します。先ほどの表から価格が乖離している場合には,数時間待ってみてください。




手順1: vastaiのアカウントを作成/準備









まずは以下のURLにアクセスして,サクッとアカウントを作成します。

Vast.ai | Console - cloud.vast.ai

Githubと連携して登録する方法が一番楽なのでお勧めです。




アカウントを作成したら,次にコンソールの「Billing」からデポジットを追加します。いくつか選択肢がありますが,まずは練習用に$5(750円)を追加するのがお勧めです。






「stripe」を選択すると,クレジットカードで支払いができます。これで,ひとまずGPUサーバーを借りる準備は完了です。




手順2: コマンドラインとAPIキーの用意









まず,pipを導入した環境で以下を実行して vastai コマンドを入れます。これは vast.ai のインスタンス契約などをコマンドラインで操作するためのツールです。

```Bash
pip install --upgrade vastai;
```





そして,公式サイトの「Keys → API Keys → New」からAPIキーを取得して,vastaiコマンドで登録します。




権限は基本的には Read / Write を与えておけば問題ありません。




APIキーを取得できたらコピーして,以下のコマンドで登録します。

```Bash
vastai set api-key
```





これでコマンドの準備も完了です。




手順3: コスパの良いインスタンスを探す









このように,コマンドライン操作で条件に見合うインスタンスを探します。

```Bash
vastai search offers \
-n \
verified=any reliability=any external=any rented=any rentable=True \
inet_up>=200 inet_down>=200 \
cpu_cores_effective>16 \
geolocation!=HK geolocation!=CN \
dph_total>=0.000 dph_total<=5.000 \
--limit 100 \
-o +dph_total,+id
```





ここでは,立ち上げにかかる時間を考慮してネットワーク速度が上下とも200Mbpsを超えている環境に絞り,さらに[けしからんファイアウォール](https://logmi.jp/main/technology/323854)を避けるために中国と香港を除外しています。

もし政府による中間者攻撃によりClient Helloが吹き飛ばされることを覚悟の上で,適切にバイパスできるなら中国リージョンのインスタンスは結構割安になりがちなので,むしろ逆に検索結果に含めてもいいかもしれません。

詳しい検索クエリの設定方法はこちらから。ここでは,Pythonスクリプトを使ってできるだけ多くのインスタンスを探索し,それぞれの vCPU あたりの単価を求めた上で上位300件を表示してみます。

作ったスクリプトは[こちら](https://gist.github.com/ActiveTK/16aa6fee916734678a337c1bbd2373a0)に置いておきます。

このように,vCPUあたりの単価が安い順で上位300件を取得することができました。




```MarkDown
ID [SCORE] vCPUs RAM $/hr N MODEL
------------------------------------------------------------------
26618941 [ 751.8] 128 252GB 0.170 1 RTX 3090
25892710 [ 748.7] 24 63GB 0.032 1 RTX 3070
26694109 [ 737.2] 40 31GB 0.054 1 GTX 1060
25891584 [ 718.8] 24 63GB 0.033 1 RTX 3060 Ti
26276649 [ 684.2] 28 63GB 0.041 1 RTX 3060
26509312 [ 593.1] 72 15GB 0.121 1 RTX 3090
26421568 [ 582.7] 28 63GB 0.048 1 RTX 3060
26421661 [ 582.7] 28 63GB 0.048 1 RTX 3060
21049054 [ 579.9] 24 31GB 0.041 1 RTX 3060
26443313 [ 579.9] 24 31GB 0.041 1 RTX 3060
------------------------------------------------------------------
TOTAL(10) 420 674GB 0.631
------------------------------------------------------------------
```





また,結果は直下に `results.json` として保存されるようにしてあります。




このようにして,コスパの良いインスタンスを抽出することができました。




手順4: 一気に立ち上げる









上で保存した `results.json` に基づいて上から順番にいくつか起動していきます。

とはいっても,大量のインスタンスは起動時間がバラバラであるため,一度立ち上げ直後にstopで課金を停止して全部用意ができた瞬間に一斉にrestartすることで,ストレージ以外の余計な費用を一切かけないように工夫します。

これも専用のPythonスクリプトを作りました。[こちら](https://gist.github.com/ActiveTK/db8583a30fbaa8ed1e97ff883644951d)をひな型として利用して,CPUやGPUの用途(動かしたいプログラム)に応じてチャッピーに編集をお願いしてください。

ひな形そのままだと,このようにして起動できます。`--start` の引数に指定された個数だけ,`results.json` の中身に含まれるインスタンスを上から順番に起動します。

```Bash
python3 vastai-loader.py --start 5 \
--screen 'main:python3 -u /work/app.py' \
--screen 'side:node /work/server.js' \
--image vastai/base-image:@vastai-automatic-tag \
--disk 16 --env 'TCP_PORTS=8000;UDP_PORTS=;' --debug
```





早速 20,450 vCPU / 70TB RAM で遊んでみる









では,いざ `vastai-loader.py` を使って上位300個のインスタンスを立ち上げてみます。




さすがに300個ともなると,restartまでかなり時間がかかりそうでした。約10分待機して218個がstop状態になったところで[Ctrl+C]でinterruptして,さらに `--cleanup` で `Running` 状態になっていないインスタンスを全部切り捨てたところ,172個のインスタンスが残りました。

本当は時間があればもっと待ってもいいのですが,今回は早めに打ち切ることを見越して,かなりリストを大きめに取ってきています。




起動途中も圧巻ですね。全部のインスタンスを画面で描画しきれていません。

今回私は,短時間ではありますが,

CPU: mkp224o + onion-vanity-address (Onionアドレスのバニティ)
GPU: GMiner (Ravencoinのマイニング)


を動かすことにしました。一応,vast.aiは規約的に「仮想通貨で支払っていること」と「提供元が個別ルールでマイニングを禁止していないこと」を条件にマイニングが許可されていることに注意してください。

CPU側のバニティは統一的に管理しやすいように,自前のVPSで集計用サイトを用意して,そこに定期的に進捗状況や発見したアドレスをPOSTするように設計しました。

そしてこれがその画面です。







このように,149個のインスタンスとHTTP Pollingによる通信に成功し,圧巻のCPU合計「15,700%」,メモリ「55,605 GB」が表示されています。

そして,mkp224oの速度は 61,516,761,500 attempts/s (61.52 Bkeys/s) 程度になりました。手元のThinkPad(i5-3320M, 2c4t)だと 100 Kkeys/s 程度になるので,単純計算でThinkPadの60万倍の性能ということになります。もちろん最適化などもあるとは思いますが,それでも古いノートPCを数十万台繋げた規模のCPUリソースです。

またマイニングの方は環境依存が小さいことからGMinerを選びましたが,ハッシュレートが約7.2 GH/s,金額に換算して\\$51.38/day程度になりました。




生きているインスタンスの合計金額から見ると約1/20倍程度なので大赤字ではありますが,検索時にさらに条件を絞って "vCPUのコスパが良く,しかもGPUもそこそこに良いもの" を検索すれば,黒字化に近づくことができるかもしれません。




最後に









今回は,vast.aiの金額設定を上手く利用することで超高性能なクラスターを破格で用意する方法を思いついたので,メモ程度に紹介させていただきました!

最後までお読みいただきありがとうございます。