Google Colab のランタイムをコードから終了させる方法

shutdown-colab-runtime プログラミング



結論

次のコードを実行するだけです.

from google.colab import runtime

runtime.unassign()

背景/動機

Google Colaboratory は手軽に Deep Learning 用のクラウド計算環境を手に入れられる素晴らしいサービスですが,有料プランである Pro / Pro+ について,月額定額制からマイルド従量課金制に変更されました.
具体的に言うと,各プランに契約している場合に,月々,有効期限が90日間の「コンピューティングユニット」というものが付与されるようになりました.
ユニット数と月額料金はそれぞれ,

  • Pro: 100(月額 1,072 円 + 税)
  • Pro+: 500(月額 5,243 円 + 税)
  • (無料版: 不明)

となっており,手持ちのコンピューティングユニットを使い切った場合は,ユニット数:100 を 1,072 円 + 税,ユニット数:500 を 5,243 円 + 税 で追加購入する必要がある仕様になりました.
筆者は Colab Pro ユーザーなので,(おそらく以前は)使いたい放題だった仕様から上記仕様に変更されたときは衝撃でした.

コンピューティングユニット数は,用いる計算環境によっても異なり,それぞれ以下のようになっています.

ハードウェアアクセラレータ1時間あたりの使用ユニット数
None(Intel(R) Xeon(R) CPU @ 2.20GHz ✕ 2)約 0.08
GPU(標準:NVIDIA T4)約 1.96
GPU(プレミアム:NVIDIA V100)約 5.36
GPU(プレミアム:NVIDIA A100)約 13.08
TPU(TPU v2)約 1.96

上表は一昔前の区分で,知らぬ間に以下の仕様のように,アクセラレータが明示的に指定できるようになりました(ただし,使用状況によっては,特に pro+ 以外で高スペックの A100 を指定すると,指定スペックと異なったものが割り当てられる場合あり).

[選択式]
ハードウェア
アクセラレータ
[選択式]
GPUのタイプ
[選択式]
ランタイムの仕様
1時間あたりの 使用ユニット数CPUアクセラレータ
None標準約 0.08Intel(R) Xeon(R) CPU @ 2.20GHz ✕ 2
Noneハイメモリ約 0.12Intel(R) Xeon(R) CPU @ 2.20GHz ✕ 4
GPUT4標準約 1.96Intel(R) Xeon(R) CPU @ 2.30GHz ✕ 2NVIDIA T4
GPUT4ハイメモリ約 2.05Intel(R) Xeon(R) CPU @ 2.30GHz ✕ 4NVIDIA T4
GPUV100標準約 5.36Intel(R) Xeon(R) CPU @ 2.30GHz ✕ 2NVIDIA V100
GPUV100ハイメモリ約 5.45Intel(R) Xeon(R) CPU @ 2.00GHz ✕ 4NVIDIA V100
GPUA100ハイメモリNVIDIA A100
TPU標準約 1.96Intel(R) Xeon(R) CPU @ 2.30GHz ✕ 2TPU v2
TPUハイメモリ約 2.05Intel(R) Xeon(R) CPU @ 2.30GHz ✕ 40TPU v2
※ A100 について,記事修正時の夜間では colab pro 契約でも中々割り当てられなかったため保留

そして,気をつけなければならないのが,このユニット数は,計算時間ではなく,「ランタイムを接続している時間」によって減っていきます.
なんと,GPU / TPU のランタイムで計算走らせっぱなしで放っておくと,ユニット数がすぐに底をついてしまいます.
Pro+ ユーザーならばバックグラウンドで実行できてしまうため,全く気づかないうちにユニット数を浪費してしまいます.
このため,計算が終わったらこまめにランタイムを終了させたいところですが,計算時間の長い Deep Learning が終わるのを横目に待っているのも面倒です.
従いまして,タイトルの通り,計算が終わったりエラーで止まった場合に,「接続中のランタイムをコードから終了させる」ということについて調査した結果,関数が用意されていたのですごく簡単に実装できましたので紹介します.

コード実行例と説明

以下リンクの google/colab/runtime.py を見たら unassign という関数が用意されており,これをインポートし実行したら,コード実行でランタイムが終了できました.

GitHub - googlecolab/colabtools: Python libraries for Google Colaboratory
Python libraries for Google Colaboratory. Contribute to googlecolab/colabtools development by creating an account on Git...

以下のコードは,colab 上でコードブロック1,2,3のように実行していくような形で記載しました.

import time

t_start = time.perf_counter()


def t_elapsed(t):
    return time.perf_counter() - t


print(t_elapsed(t=t_start))
# 0.00017659900001376627 : 経過時間を出力
from google.colab import runtime

runtime.unassign()
print(t_elapsed(t=t_start))
# ---------------------------------------------------------------------------
# NameError                                 Traceback (most recent call last)
# <ipython-input-1-9bde2da830c3> in <module>
# ----> 1 print(t_elapsed(t=t_start))
#
# NameError: name 't_elapsed' is not defined

ブロック1では,経過時間を返す関数:t_elapsed を定義しています.
ブロック2で,ランタイム接続を切っています.
するとブロック3では,t_elapsed を呼び出しても「’t_elapsed’ は定義されていない」とエラーを返しています.
つまり,ブロック2できちんとランタイム接続が切れていることが分かります.

このブロック2のコードを計算の最後や,エラーの例外処理に仕込んでおけば,不用意にコンピューテkィングユニット数を浪費することの低減につながることでしょう(Slack や Discord への通知は,これの前に書くように注意が必要です).

コメント

タイトルとURLをコピーしました