RunPod
ここから参加すると pokutuna.icon にもあなたにもクレジットが付与されます
ssh 接続
環境変数
Secrets に色々入れておいてあれこれ参照させる
これ押すの意外と忘れる問題
https://gyazo.com/c32d0358597ab497e667ff52dbd2cb9d
code:envs
GOOGLE_CLOUD_PROJECT="{{ RUNPOD_SECRET_GOOGLE_CLOUD_PROJECT }}"
CLOUDSDK_CONFIG=/workspace/.config/gcloud
GOOGLE_APPLICATION_CREDENTIALS=/workspace/.config/gcloud/application_default_credentials.json
HF_HOME=/workspace/.cache/huggingface
HF_TOKEN="{{ RUNPOD_SECRET_HF_TOKEN }}"
WANDB_PROJECT="{何か適当に決める}"
WANDB_API_KEY="{{ RUNPOD_SECRET_WANDB_API_KEY }}"
WANDB_DIR="/workspace/wandb/logs"
KAGGLE_API_KEY="{{ RUNPOD_SECRET_KAGGLE_API_KEY }}"
TOKENIZERS_PARALLELISM=false
GITHUB_TOKEN="{{ RUNPOD_SECRET_GITHUB_TOKEN }}"
UV_CACHE_DIR=/workspace/.cache/uv
ここで適当に PATH 設定すると起動時にコマンドがもろもろ足りないので PATH を追加する場合は以下も足す
/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
code:envs
PATH=/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/workspace/tools/google-cloud-sdk/bin:/workspace/tools/gh/bin:/workspace/tools/uv/bin
gcloud 使う時は CLOUDSDK_CONFIG 設定した1 度 gcloud auth login して認証情報残す
UV_CACHE_DIR はデフォルトで $HOME/.cache/uv
NetworkVolume を使う場合 filesystem が違うのでハードリンクにできずコピーになるので volume 側においておくのが良い
Python 依存の管理
素直に uv 使う
↑の環境変数のように UV_CACHE_DIR を設定しておく
template の pytorch イメージに色々入っているものと重複するのは気になる
その場合 pyproject.toml に書かない
system を使うなら uv で管理しておいて uv pip install --system -e . する?
作業終わったら Pod 終了する
runpodctl コマンドとデフォルトの環境変数 $RUNPOD_POD_ID で Pod 内から自身を停止できる
$ runpodctl stop pod $RUNPOD_POD_ID
notebook の最後やコマンドの後、学習 & 保存したあとにこれ実行したらいい
途中でコケても実行させたいので notebook 実行の時は ssh 側でも安全装置するかな?
$ sleep 2h && runpodctl stop pod $RUNPOD_POD_ID
COMMAND を実行して終わったら 10 回ベル鳴らして 1分待機、C-c しなかったら Pod 止める
$COMMAND; for i in {1..5}; do echo -e '\a'; sleep 0.1; done; sleep 60; runpodctl stop pod $RUNPOD_POD_ID
code:コピペ用.sh
; for i in {1..5}; do echo -e '\a'; sleep 0.1; done; sleep 60; runpodctl stop pod $RUNPOD_POD_ID
ツールのインストール & workspace 下への配置
code:install_once.sh
# dirs
mkdir -p /workspace/.cache/huggingface
mkdir -p /workspace/.cache/uv
mkdir -p /workspace/tools/
# gcloud
bash install.sh --disable-prompts --install-dir=/workspace/tools
地味に時間がかかる、出力ファイルのログでなくていいし gcloud storage & bq が使えるだけでいいんだけど
/workspace/tools/google-cloud-sdk/bin 以下に配置される
code:install_once.sh
# gh
/worksapce/tools/gh/bin/gh を使う
$ gh repo clone pokutuna/hogehoge kaggle で clone できる / $ gh repo sync で push & pull
fine-grained な PAT はあるが SSH キーやログイン情報はないので gh コマンドでやりくりする、まあ十分
code:install_once.sh
# uv
NetworkVolume
Network Volume のほうが Pod の Storage より安い $0.07/GB/month
Stopped Pod は $0.20/GB/month
容量はあとから増やせるので大きくしすぎなくて良い
S3 互換 API がある
Pod 起動前、つまり GPU 代気にせず巨大なファイル配置できるので便利
awscli も使える
$ aws s3 ls --profile=runpod s3://VOLUME_ID/
たとえば eu-ro-1 なら
code:~/.aws/config
region = eu-ro-1
code:~/.aws/credentials
aws_access_key_id = user_...
aws_secret_access_key = rps_...
S3 互換 API で起動前にモデルを Network Volume に置いておく
H100 とか借りて charge が発生している時間で巨大モデルダウンロードするの無駄すぎるので
Colab で HuggingFace モデルをダウンロードして Runpod に配置するテク(ひどい)
code:cell.py
!pip install awscli
from google.colab import userdata
%env HF_TOKEN={userdata.get('HF_TOKEN')}
%env AWS_ACCESS_KEY_ID={userdata.get('RUNPOD_STORAGE_ACCESS_KEY_ID')}
%env AWS_SECRET_ACCESS_KEY={userdata.get('RUNPOD_STORAGE_SECRET_ACCESS_KEY')}
code:cell.py
model = "Qwen/Qwen3-8B"
!HF_HUB_ENABLE_HF_TRANSFER=1 hf download $model --local-dir=/content/models/$model
code:cell.py
!aws s3 sync /content/models/$model s3://VOLUME/models/$model --region=REGION --endpoint-url=ENDPOINT
偶に一部が失敗するので upload failed 無いか見る
一部失敗したときは --checksum-algorithm=CRC32C など(常に付けても良い)
fatal error: Error during pagination: The same next token was received twice: ...
ListObject にコケるんだろうから s3 cp --recursive したらうまくいくが差分だけ上げたりはできない
リトライ付きの公式のスクリプト
消しづらいしゴチャつくので huggingface の cache を上げるより model 個別に上げるほうがいい
これ Colab がいい感じに ASIA で動いてたら非効率な感じするねえ...
HF → Colab(ASIA) → Runpod (US or EU) みたいな転送になる
Google Cloud → HuggingFace へのアップロードは笑えるくらい速いんだけど
GPU なしモードは脱出用
実は GPU 1 枚時の 1/2 なだけでさしてお得じゃない
スペックは 0.5vCPU 0.5Gi に落とされる、セットアップやモデルダウンロードするのややキツいしあまり意味はない
16vCPU 251GBmem + H100 80GB ← $2.62/h
0.5vCPU 0.5GB ← $1.31/h
と考えるといかにアホなことをしようとしていたかわかる
もう NetworkVolume が良い派なので使わないかなあ