Slurm は Kaggle で役に立つ
1. はじめに
Slurm は、スパコンや研究室の GPU クラスタでよく使われるジョブスケジューラです。投入されたジョブをキューに並べておいて、CPU・メモリ・GPU が空いたものから順に実行してくれます。
「大きなクラスタのための道具でしょ?」という印象がありますが、実は自宅の GPU 1 枚で Kaggle をするときにも、めちゃくちゃ役に立ちました!Kaggle の RSNA Knee Abnormality Detection(膝 MRI の異常検出)に RTX 3090 1 枚で参加したとき、学習ジョブの管理に Slurm を使っていたんです。41 日間で、RSNA の学習だけで 253 本のジョブを回して、GPU を延べ 469 時間も使いました。ここで紹介する方法は一般化してあるので、どんな GPU でも使えると思います!3090 は Kaggle で戦うにはつらいことは置いておいてくださいw
Claude Code や Codex に実験を任せるなら、なおさらおすすめです。学習を Slurm に投げておけば、エージェントのセッションが切れても学習はそのまま走り続けてくれます。
3 行でいうと、こんな感じです。
GPU 1 枚のジョブキューなら、Ray や Kubernetes より入れるものが少なくて済みます。導入も Codex に任せたら約 25 分で終わりました
学習を Slurm に任せておけば、Claude Code や Codex のセッションが切れても学習は止まりません
別のコンペのジョブも同じキューに入れれば、1 枚の GPU を順番に分け合えます。優先度も変えられます
Slurm のコマンドの基本は、Turing の ymg_aq さんの記事「手元のGPUを遊ばせないためのジョブスケジューラ入門」がとても丁寧にまとめてくれています。なのでこの記事では、Kaggle の実験で実際に使った設定と、エージェントと組み合わせるときの工夫を中心に紹介していきますね。
2. GPU 1 枚あるある
まずは、自宅の GPU 1 枚で実験していて「うわ、困った…」となったことを並べてみます。
GPU がサボる。 学習が終わったことに気づかないと、次の実験を始めるまで GPU は止まったままです。「前のジョブが終わったら次を投入する」処理を tmux の sleep ループで書いたこともありますが、ループ自体がエラーも出さずに止まっていたことがありました。ひどい…
エージェントが力尽きると、学習も道連れになる。 Claude Code などのバックグラウンドタスクで学習を動かしていると、セッションが終わったときに学習も止まっちゃいます。うっかりセッションを閉じてしまうこともありますし、Codex や Claude の利用上限でエージェントのループが止まることもありますよね
別のコンペと GPU を取り合う。 別のコンペの実験も同じ GPU で動かそうとすると、どっちが先に使うかを人間が調整することになります。メモリが足りなくなって、どちらかが強制終了されることもありました
どれも、Slurm に任せるとかなり楽になりますよ!
3. Slurm とは
Slurm は 2 つのデーモンで動いています。ジョブを受け付けて資源を割り当てる slurmctld と、実際にジョブを実行する slurmd です。munge は、この 2 つがお互いを認証するために使います。ジョブは、パーティションと呼ばれる投入先に sbatch コマンドで入れます。
もともとは多数のノードをまとめて管理するための道具ですが、1 台で使うなら、同じマシンで slurmctld と slurmd を動かすだけです。しかも、キューの状態は slurmctld が StateSaveLocation のディレクトリに保存してくれるので、デーモンを再起動してもキューは消えません!
ちなみに Slurm には、終わったジョブの記録をデータベースに残す accounting という機能もあります。今回は入れていません。その代わりの工夫は 5.4 で紹介しますね。
4. 導入は Codex 任せで 25 分
「でも導入が大変なんでしょ?」と思ったあなた、安心してください。導入の手間は、ほとんど Claude や Codex が引き受けてくれます。
この章に載せている slurm.conf・gres.conf・cgroup.conf とセットアップスクリプトは、ぜんぶ Codex が書いたものです。私がやったのは sudo bash scripts/setup_slurm.sh を実行したことだけ!sudo が要る操作だけは自分で打ちます。入れると決めてから動くまで、約 25 分でした。slurm.conf の書き方を一から覚える必要もありません。
入れたあとも同じです。今の時代、Claude に「GPU のジョブは Slurm 経由で動かして」と頼めば、難しいジョブ定義を自分で書かなくても、いい感じに Slurm 経由にしてくれます!
使った環境はこんな感じです。
項目
内容
マシン
自宅のデスクトップ 1 台(Ubuntu 26.04.1 LTS)
CPU / メモリ
10 コア 20 スレッド / 61GB。Slurm には 54,000MB として登録
GPU
RTX 3090(24GB)1 枚。画面表示にも使用
Slurm
Ubuntu のパッケージの slurm-wlm 25.11.2。accounting はなし
セットアップスクリプトは、root 以外で実行すると止まるようにしてあります。それと、/etc/slurm/ に違う内容の設定ファイルがあるときは、上書きせずに止まります。
scripts/setup_slurm.sh
#!/usr/bin/env bash
Explicit host-admin setup. Never run the experiment controller as root.
set -euo pipefail
if [[ $EUID != 0 ]]; then
echo 'Run on the host: sudo bash scripts/setup_slurm.sh' >&2
exit 1
fi
if [[ $(hostname -s) != home-ubuntu ]]; then
echo 'These configs target home-ubuntu; review the node configuration first.' >&2
exit 1
fi
for name in slurm.conf gres.conf cgroup.conf; do
if [[ -e /etc/slurm/$name ]] && ! cmp -s "ops/slurm/$name" "/etc/slurm/$name"; then
echo "Existing /etc/slurm/$name differs; refusing to overwrite." >&2
exit 1
fi
done
apt-get update
apt-get install -y slurm-wlm munge
install -d -o slurm -g slurm /var/lib/slurm/slurmctld /var/lib/slurm/slurmd /var/log/slurm
install -d -m 755 /etc/slurm
for name in slurm.conf gres.conf cgroup.conf; do
install -m 644 "ops/slurm/$name" "/etc/slurm/$name"
done
if [[ ! -s /etc/munge/munge.key ]]; then
/usr/sbin/mungekey --create
fi
systemctl enable --now munge
systemctl enable --now slurmctld slurmd
slurmd -C
slurmd -G
scontrol ping
sinfo -Nel
設定ファイルは次の 3 つです。リポジトリの ops/slurm/ に置いて、Git で管理しています。
ops/slurm/slurm.conf
Single-node desktop configuration. CPU topology is checked against slurmd -C.
ClusterName=rsna-local
SlurmctldHost=home-ubuntu
SlurmUser=slurm
AuthType=auth/munge
StateSaveLocation=/var/lib/slurm/slurmctld
SlurmdSpoolDir=/var/lib/slurm/slurmd
SlurmctldPidFile=/run/slurmctld.pid
SlurmdPidFile=/run/slurmd.pid
SlurmctldLogFile=/var/log/slurm/slurmctld.log
SlurmdLogFile=/var/log/slurm/slurmd.log
SelectType=select/cons_tres
SelectTypeParameters=CR_Core_Memory
SchedulerType=sched/backfill
ProctrackType=proctrack/cgroup
TaskPlugin=task/cgroup,task/affinity
GresTypes=gpu
ReturnToService=2
MinJobAge=86400
NodeName=home-ubuntu CPUs=20 Boards=1 SocketsPerBoard=1 CoresPerSocket=10 ThreadsPerCore=2 RealMemory=54000 Gres=gpu:1 State=UNKNOWN
PartitionName=gpu Nodes=home-ubuntu Default=YES MaxTime=08:00:00 State=UP OverSubscribe=NO
ops/slurm/gres.conf
Manual GPU registration avoids a dependency on the NVML autodetection plugin.
NodeName=home-ubuntu Name=gpu File=/dev/nvidia0
ops/slurm/cgroup.conf
CgroupPlugin=autodetect
ConstrainCores=yes
ConstrainRAMSpace=yes
ConstrainDevices=yes
設定のポイントはこのあたりです。
SelectType=select/cons_tres と CR_Core_Memory で、CPU コア・メモリ・GPU をジョブごとに別々に割り当てます
cgroup.conf の 3 つの Constrain で、ジョブが要求した分を超える CPU・メモリ・GPU を使えないようにします
gres.conf は、GPU を Slurm に登録するファイルです。NVIDIA の管理ライブラリ NVML による自動検出には頼らず、/dev/nvidia0 を手で書きました。ただ、これはカーネルを更新したときに裏目に出ます(10.2 で書きます)
MinJobAge=86400 で、終わったジョブも 24 時間は scontrol で見られるようにしています。accounting の代わりですね
ReturnToService=2 は、再起動したノードを自動で使える状態に戻す設定です
パーティションは gpu の 1 つだけにして、1 ジョブの上限は 8 時間にしました
5. 基本的な使い方
ここからは、実験で実際に使ったコマンドを順に見ていきましょう!
5.1 sbatch でジョブを投入する
sbatch でジョブを投げると、ジョブはキューに入ります。GPU が使われていれば、空くまで何時間でも待って、空いたらすぐ始まります。寝ている間も GPU に働いてもらえるのは、これのおかげです!
GPU を使う学習の投入は、次のラッパースクリプトだけを使うことにしました。資源の要求(--gres=gpu:1、CPU 8 コア、メモリ 28G)をこの 1 か所に固定しておけば、GPU の指定を付け忘れる心配がありません。2 つ目の引数にジョブ ID を渡すと、そのジョブの後ろにつなげます(5.2 で説明します)。それと、再投入のたびにログのファイル名を attempt1.out、attempt2.out と変えるので、前の試行のログが上書きされることもありません。
scripts/gpu_submit.sh(コメントを省略)
scripts/gpu_submit.sh <TAG> [afterany-jobid] [mem]
set -euo pipefail
cd "$(dirname "$0")/.."
TAG="${1:?usage: gpu_submit.sh <TAG> [afterany-jobid]}"
AFTER="${2:-}"
MEM="${3:-28G}"
JOB="runs/dino/$TAG/job.sh"
[ -x "$JOB" ] || { echo "no executable $JOB" >&2; exit 1; }
mkdir -p "runs/dino/$TAG/slurm"
N=1; while [ -e "runs/dino/$TAG/slurm/attempt$N.out" ]; do N=$((N+1)); done
DEP=()
[ -n "$AFTER" ] && DEP=(--dependency="afterany:$AFTER")
sbatch --parsable -p gpu --gres=gpu:1 -c 8 --mem="$MEM" -J "$TAG" \
-o "runs/dino/$TAG/slurm/attempt$N.out" "${DEP[@]}" "$JOB"
5.2 --dependency でジョブをつなぐ
ジョブどうしの順番は、依存関係で決められます。sbatch に --dependency=afterany:<ジョブ ID> を付けて投げると、そのジョブは、指定したジョブが終わるまでキューの中で待ちます。afterany は、前のジョブが成功でも失敗でも、終わったら始まるタイプです。前のジョブが成功したときだけ始めたいなら、afterok を使います。
JOB1=$(sbatch --parsable train_a.sh) # --parsable を付けると、ジョブ ID だけが出力される
sbatch --dependency=afterany:$JOB1 train_b.sh # JOB1 が終わったら、成否にかかわらず始める
sbatch --dependency=afterok:$JOB1 eval_a.sh # JOB1 が成功したときだけ始める
--parsable で受け取ったジョブ ID を次の投入に渡していけば、ジョブを何本でも数珠つなぎにできます。afterany なら、途中の 1 本が失敗しても後ろのジョブは止まりません。しかも依存関係は slurmctld が持っているので、tmux やエージェントのセッションが終わっても消えません。黙って止まる sleep ループとは、これでお別れです!
ちなみに、優先度が同じなら、ジョブはだいたい投入順に始まります。ただ、必ずそうなるとは限りません。Slurm は、先頭のジョブの開始を遅らせない範囲で、後ろの小さなジョブを先に始めることがあるんです(backfill と呼びます)。順番が大事なジョブは、afterany でつないで明示しておくと安心ですよ。
5.3 squeue で予定表を見る
squeue は、キューに入っているジョブの一覧を出すコマンドです。ジョブ名(-J)を実験のタグにしておくと、squeue の出力がそのまま実験の予定表になって便利です。
ただひとつ注意があります。Slurm は仕事はきっちりやってくれますが、報告はしてくれません。キューが空になれば GPU は止まったままですし、ジョブが終わったことも誰にも教えてくれないんです。私も、ジョブの完了に気づかずに GPU を約 10 時間空けてしまったことがあります…。
その対策として、次のジョブを常に 1 本、後ろに並べておくようにしました。さらに、squeue を監視する小さな常駐プログラムを作って、ジョブがキューから抜けたとき、残りが 1 本になったとき、キューが空になったときにだけ通知が来るようにしています。
5.4 scontrol show job で成否を確かめる
accounting を入れていないので、終わったジョブの記録を調べる sacct は使えません。代わりに活躍するのが、ジョブやノードの状態を見たり変えたりできる scontrol です。slurm.conf に MinJobAge=86400 を書いて、終わったジョブも 24 時間は scontrol で見えるようにしています。
実験ループでは、squeue -h -j <ジョブ ID> が空になるまで待ってから、scontrol show job <ジョブ ID> -o を読みます。JobState=COMPLETED、ExitCode=0:0、結果ファイル cv.json の 3 つがそろったときだけ成功、というルールです。24 時間を過ぎると scontrol からも消えちゃうので、結果はループの状態ファイルに書いておきます。
5.5 scontrol update と --test-only で、待っているジョブを調整する
投入済みのジョブの資源は、投げ直さなくても変えられます。たとえばメモリの要求なら、scontrol update job=<ID> MinMemoryNode=28672 といった感じです。単位は MB なので、28G と書くと "Invalid MinMemoryNode value" で怒られます。ジョブ ID も依存関係もそのまま残るので、地味に便利です!
ジョブがいつ始まりそうかは、sbatch --test-only で調べられます。同じ条件で --gres=gpu:1 の有無だけを変えて試すと、待っている原因がメモリなのか GPU なのかが分かりますよ。
5.6 scancel で取り消して、投入し直す
Slurm は、投入されたバッチスクリプトの写しを、投入した時点で保存します。なので、投げたあとに job.sh を直しても、待っているジョブには反映されません。直したいときは、scancel で取り消して投げ直しましょう。bash -n の構文チェックでは、exec の行が消えたようなミスは見つからないので、書き込む前に中身を確かめておくのがおすすめです。
一方、Python のコードは、ジョブが始まったときに読まれます。予約したあとで train.py を直せば反映されますが、壊すと待っているジョブが全部失敗します。引数の検証も開始時にしか動かないので、投入する前に、その引数で検証だけ先に実行しておくと安心です。
6. Slurm × Claude Code / Codex
ここからは、エージェントに実験を任せるときの使い方です。
6.1 セッションが力尽きても、学習は止まらない
Slurm に投げた学習は、Slurm の管理下で動きます。投入したエージェントのプロセスとは関係がないので、Claude Code や Codex のセッションが切れても、利用上限でループが止まっても、学習は動き続けます!
実験ループの説明書にも、こう書いておきました。
チャットを閉じてもtmuxとSlurmの処理は続きます。マシンの停止・再起動は別です。
6.2 覚えておくのは、エージェントではなくリポジトリ
学習をエージェントから切り離すなら、「何を試して、結果がどうだったか」もエージェントの外に置いておく必要があります。Slurm が知っているのは、どのジョブが待っていて、どれが動いているかだけですからね。そこで、実験の状態はリポジトリのファイルに書いて、エージェントはそのファイルと squeue を読んで作業を続けるようにしました。
実験 1 本ごとに、省略なしのコマンドを runs/dino/<タグ>/job.sh に書きます。新しい実験は、実績のある job.sh の変数を 1 つだけ変えて作ります
学習ログの書式は、AGENTS.md(Claude Code や Codex が読む作業ルール)で決めています。先頭の行に START と設定と使うデバイスを書いて、30〜60 秒ごとに loss・速度・VRAM・残り時間を 1 行ずつ出します。最終行は必ず FINISHED か FAILED です。tqdm はキャリッジリターンのせいで tail -f で読めなくなるので、使いません
判断の経緯は ops/decisions.md に追記します
AGENTS.md には「sbatch を手で書かない。投入は gpu_submit.sh だけ」と書いておきます
エージェントが作業を再開するときの手順も、最初の項目を「squeue -h が空なら、既存の job.sh をコピーして 1 変数だけ変えた次の実験をすぐ投入する」にしておきました。
7. 複数のコンペで GPU を分け合う
7.1 同じパーティションに投入する
別のコンペのジョブも同じパーティションに入れておけば、Slurm が順番に GPU を割り当ててくれます。私の環境では、RSNA のほかに ARC Prize 2026 と、もう 1 つ別のプロジェクトのジョブも、同じ gpu パーティションに投げていました。優先度が同じなら投入順に始まるので、どっちが先に GPU を使うかを人間が調整する必要はありません!
自分のジョブを、別プロジェクトが最後に投げたジョブの後ろに afterany でつなぐ、という使い方もできます。相手が早く終わっても途中で失敗しても、すぐにこちらのジョブが始まるので、GPU が遊びません。
7.2 評価から集計まで、依存関係でまとめて予約する
依存関係を組み合わせると、次のようなジョブを 1 回のスクリプト実行でまとめて予約できます。
ベースモデルの評価
2 つの条件での学習
条件ごとの評価
集計と Discord への投稿
次のスクリプトは、ARC Prize 側で使った投入スクリプトから、ジョブの名前と中身を省いて、組み方だけを残したものです。
submit.sh(名前と中身を省略)
common() { # ジョブ名, GPU を使うか(0/1), 制限時間。#SBATCH の行はすべて最初のコマンドより前に置く
echo "#!/bin/bash"
echo "#SBATCH -J $1 -p gpu -c 4 --mem=16G -t $3 -o $WORK/logs/%j-$1.out"
if [ "$2" = 1 ]; then echo "#SBATCH --gres=gpu:1"; fi
case "$1" in train-*) echo "#SBATCH --signal=B:TERM@300";; esac # 学習は SIGTERM を受けると resume.pt を保存する
echo "set -euo pipefail; cd $REPO"
}
j1=$( { common eval-base 1 03:00:00; echo "<ベースモデルの評価>"; } | sbatch --parsable )
j2=$( { common train-a 1 08:00:00; echo "<条件 A の学習>"; } | sbatch --parsable )
j3=$( { common train-b 1 08:00:00; echo "<条件 B の学習>"; } \
| sbatch --parsable --dependency=afterok:$j1 --kill-on-invalid-dep=yes )
j4=$( { common eval-a 1 03:00:00; echo "<条件 A の評価>"; } \
| sbatch --parsable --dependency=afterok:$j2 --kill-on-invalid-dep=yes )
j5=$( { common eval-b 1 03:00:00; echo "<条件 B の評価>"; } \
| sbatch --parsable --dependency=afterok:$j3 --kill-on-invalid-dep=yes )
j6=$( { common report 0 00:10:00; echo "<集計と Discord への投稿>"; } \
| sbatch --parsable --dependency=afterany:$j4:$j5:$j1:$j2:$j3 --kill-on-invalid-dep=no )
ポイントはこのあたりです。
条件 B の学習はベースモデルの評価で作るファイルを使うので、afterok で評価の成功を待ちます。評価は学習が成功したときだけ実行して、集計は afterany で何があっても最後に実行します
--kill-on-invalid-dep=yes を付けておくと、前のジョブが失敗して依存関係を満たせなくなったジョブを、Slurm がキューから消してくれます
--signal=B:TERM@300 は、制限時間の 300 秒前に、バッチスクリプトのシェルへ SIGTERM を送る指定です。学習側は SIGTERM を受けると resume.pt を保存します
集計ジョブは GPU を使わないので、--gres を付けずに CPU だけのジョブにしています
#SBATCH の行を含むスクリプトを関数の出力として組み立てて、標準入力から sbatch に渡しています。ちょっとトリッキーですが、意外と快適です
7.3 優先度を変える(未検証)
コンペごとに優先度を変えたいときの手段は、次のとおりです。今回は使っていないので、Slurm のドキュメントで調べた内容になります。
sbatch --nice=100 や scontrol update job=<ID> nice=100 で、ジョブの優先度を下げられます。負の値で優先度を上げられるのは、特権ユーザーだけです(sbatch、scontrol)
scontrol top <ID> で、同じユーザー・パーティション・アカウント・QOS のジョブの中で、指定したジョブを先頭に移せます。QOS は、ジョブの種類ごとに優先度や上限を決める設定のことです。一般ユーザーには既定で無効なので、slurm.conf に SchedulerParameters=enable_user_top を書く必要があります
root なら、scontrol update job=<ID> priority=<値> で優先度を直接決められます。決めた値は固定されて、優先度プラグインは更新しなくなります。プラグインに戻すには、ジョブを hold してから release します
コンペごとにパーティションを分けて PriorityTier を変える方法や、QOS を分ける方法もあります
空いた時間にだけ別の実験を入れたい場合は、優先度の高いジョブのために実行中のジョブを止める preemption という機能もあります。こちらも試していないので、私は投入の前後に条件を確かめる仕組みを自作しました。投げる前に、他のジョブがないこと、nvidia-smi に計算プロセスがないこと、メモリとディスクの空きが足りていることをチェックします。メインの実験が GPU を必要としたら、学習側が自分から終了してくれる作りです。
8. メモリをジョブごとに区切る
cgroup.conf で設定しておくと、Slurm は、ジョブが要求した分を超える CPU・メモリ・GPU を、cgroup(Linux の資源制限の仕組み)で使えなくしてくれます。GPU を要求しなかったジョブからは、GPU が見えません。
これが特に効いてくるのが、メモリが足りなくなったときです。以前、tmux で動かしていた前処理(8 workers、22GB)が、systemd-oomd にユーザーのスコープごと強制終了されたことがありました。ところが、同時に Slurm で動いていた学習は無事だったんです!Slurm のジョブは、systemd-oomd が監視しているユーザーのスコープの外で動いているからですね。それからは、重い前処理にも --mem を付けて Slurm に投げるようにしています。
ただし、Slurm が数えるのは自分のジョブのメモリだけです。Slurm の外で動かしたプロセスの分は数えてくれないので、ジョブの横で大きな処理を動かすと、OOM killer に止められることがあります。そこは気をつけてください。
8.1 GPU ジョブどうしは、メモリを減らしても同時には動かない
GPU が 1 枚なら、GPU を要求するジョブどうしは、メモリ要求をいくら減らしても同時には動きません。メモリの合計が問題になるのは、GPU ジョブの横で、--gres を付けない CPU だけのジョブ(前処理や集計)を動かすときです。
ノードに登録したメモリは 54,000MB です。たとえば学習ジョブが --mem=40G だと、別のコンペの --mem=16G のジョブは横で動けません。40 + 16 が 54 を超えちゃうからです。
8.2 メモリ要求は、memory.peak ではなく anon と shmem で見積もる
では、学習ジョブに本当に必要なメモリはどれくらいなんでしょうか。実行中のジョブの cgroup のファイルを直接読むと分かります。
CG=/sys/fs/cgroup/system.slice/home-ubuntu_slurmstepd.scope/job_<ジョブ ID>
cat $CG/memory.peak # 33.9GB
grep -E '^(anon|shmem) ' $CG/memory.stat # anon 4.5G、shmem 6.2G
cat $CG/memory.events # high 0 max 0 oom 0 oom_kill 0
コメントの値は、ある学習ジョブで測ったものです。memory.peak は 33.9GB で、数字だけ見るとかなりの大食いですよね。でも、このうち解放できないのは、プロセスが確保したメモリ(anon)と共有メモリ(shmem)で、合わせて約 11GB だけでした!残りは、mmap で読んでいる画像キャッシュがページキャッシュとして載っていた分で、必要になればいつでも解放できます。memory.events を見ても、制限には一度も近づいていません。
そこで、既定を 28G に下げました。28 + 16 = 44 なので、別のコンペの CPU ジョブも横で動けます。ただし、注意点が 3 つあります。
メモリの上限が小さい cgroup ほどページキャッシュが強く回収されるので、下げたあとは 1 step あたりの時間が遅くなっていないかを確かめましょう
学習中より評価中のほうがメモリを使う構成もあります。28G では、学習のあとの推論の途中で OOM killer に強制終了されたモデルがあって、そのモデルは 36G にしました。測るなら、評価まで含めて測るのがおすすめです
cgroup はジョブが終わると消えちゃうので、実行中に一定の間隔で値を記録しておきましょう
OOM で強制終了されたときは、学習ログには traceback も FINISHED も出ません。slurmd のログにだけ、次のような行が残ります。
error: Detected 4 oom_kill events in StepId=280.batch.
9. Ray や Kubernetes じゃだめなの?
!
Ray と Kubernetes は今回試していません。この章は、ドキュメントと issue を読んで比べた内容です。
だめではないんです。ただ、GPU 1 枚のジョブキューとして使うには、どちらも Slurm より手間がかかります。しかも、手間のかかり方が 2 つでかなり違うんですよね。
9.1 Kubernetes は、まずクラスタを組むところから
いちばん大きな差は、Kubernetes だとクラスタの構築から始めることになる点です。Kubernetes は、複数のノードでクラスタを組む前提で作られています。kubeadm で組む場合、既定ではコントロールプレーン(クラスタを管理するノード)に Pod を載せません。1 台で動かすには、この制限(taint)を外す手順が要ります(kubeadm のドキュメント)。Pod どうしが通信するためのネットワークアドオン(CNI)も入れる必要があって、入れるまではクラスタ内の DNS(CoreDNS)も起動しません。
GPU を使うには、さらに NVIDIA の device plugin が要ります。その前提として、nvidia-container-toolkit を入れて、nvidia-container-runtime をコンテナの既定のランタイムに設定します。学習コードも、コンテナイメージにまとめることになります。ジョブを待たせて順に実行したければ、そのうえで Kueue のような、ジョブの受け入れを管理する仕組みも入れます。
k3s や minikube のような 1 台向けの配布版を使えば構築は楽になりますが、device plugin やコンテナイメージ、Kueue が要るのは変わりません。Kaggle の学習を 1 台で順番に回したいだけなのに、やることが多すぎます…。
9.2 Ray は 1 台でもすぐ動くが、キューとしては物足りない
Ray は事情がちょっと違います。Ray のドキュメントには、ノートパソコンでも 1 台のサーバーでも動かせると書いてあって、ray start --head で 1 ノードの Ray が立ち上がります。pip で入るし、root 権限も要りません。インストールの手軽さなら、Ray のほうが上です。Slurm は apt で入れるものの sudo が必要で、munge の鍵や cgroup の設定もありますからね。
でも、Ray との差が出るのは、夜のうちにジョブを何本も並べておく、キューとしての使い方なんです。
1 つ目は、キューが残るかどうか。Slurm は、キューの状態を StateSaveLocation のディレクトリに保存します(slurm.conf)。Ray では、クラスタの状態を持つ GCS(Global Control Service)が、既定ではすべてをメモリに置きます。Ray のドキュメントによると、GCS が止まるとクラスタ全体が止まります。状態を残したければ、外部の Redis か、alpha 版の RocksDB バックエンドが必要です。
2 つ目は、開始をどれだけ待てるか。Ray Jobs でも、エントリーポイントに GPU を予約して投げれば、GPU が空くまで開始を待ってくれます。ただ、この開始待ちにはタイムアウトがあります。issue #41437 では、ジョブが「Job supervisor actor failed to start within 900.0 seconds.」というエラーで失敗しています。上限は RAY_JOB_START_TIMEOUT_SECONDS で変えられますが、大きくしておかないと、前のジョブが何時間も GPU を使っている間に、後ろのジョブが開始待ちのまま失敗しちゃいます。Slurm のジョブは、資源が空くまで何時間でも待ってくれます。
3 つ目は、ジョブどうしの依存関係。Slurm なら --dependency=afterany:<ジョブ ID> と書くだけです。
9.3 1 台なら、Slurm がいちばん入れるものが少ない
というわけで、GPU 1 枚でジョブキューが欲しいなら、Ray や Kubernetes より Slurm のほうが入れるものが少なく済む、というのが私の結論です。Slurm もクラスタ向けの道具ですが、1 台なら、デーモン 2 つと munge、設定ファイル 3 つで動きます。ただし、保守の手間はかかります。10.2 のように、カーネルを更新したあとに sudo で直す場面もありました。
10. ハマりどころ
最後に、運用中にハマったところをまとめておきます。同じ轍を踏まないでくださいね…!
10.1 --gres=gpu:1 を忘れると、GPU を使えない GPU ジョブになる
--gres=gpu:1 を付けずに投げたジョブにも、Slurm は CPU とメモリだけを割り当てて、普通に開始します。cgroup の ConstrainDevices=yes で GPU が見えなくなるので、学習は数秒で "CUDA unavailable" と言って止まります。私の環境では、afterany でつないだ後ろのジョブも同じように止まって、GPU が 2.4 時間空いてしまいました。
紛らわしいのは、scontrol show job の ReqTRES=cpu=8,mem=40G,node=1,billing=8 の欄に、GPU の要求(gres)が出ないことです。この欄を写して sbatch を手で書くと、GPU の指定が抜けます。投入をラッパースクリプトにまとめたのは、これが理由でした。
!
ジョブが GPU を持っているかは、ReqTRES ではなく、scontrol show job の TresPerNode=gres/gpu:1 か、scontrol show node -d の GresUsed=gpu:1 で確かめてください。ReqTRES に GPU がなくても、GPU を要求していないとは限りません。
再投入したあとは、新しいログに device=NVIDIA GeForce RTX 3090 free=21.47GiB のような行が出たのを確かめるまで、直ったとは見なさないようにしています。
10.2 カーネルを更新したら、slurmd が起きてこない
カーネルが上がったのに、NVIDIA のカーネルモジュールが古いカーネル向けしか入っていないと、/dev/nvidia0 ができません。gres.conf に /dev/nvidia0 を手で書いていると、slurmd は gres.conf を読むところでエラーになって、起動しなくなります。
slurmd[4420]: fatal: can't stat gres.conf file /dev/nvidia0: No such file or directory
こうなると、sinfo はノードを down*(停止して応答しない状態)と表示しますし、学習中だったジョブは失われます。復旧には sudo が要ります。私の環境では、次のコマンドで戻りました。
sudo apt install -y linux-modules-nvidia-595-open-7.0.0-38-generic \
&& sudo modprobe nvidia && nvidia-smi \
&& sudo systemctl restart slurmd \
&& sudo scontrol update nodename=home-ubuntu state=resume
カーネルの自動更新を止めるか、再起動のあとに nvidia-smi と sinfo を確かめる習慣をつけておくといいと思います。
10.3 止まったジョブが、まだ RUNNING だと言い張る
マシンがフリーズして戻ってきたあと、学習のプロセスはもうないのに、Slurm が JobState=RUNNING を返し続けたことがありました。nvidia-smi を見ても、デスクトップ画面の分しか出ていません。
!
再起動やフリーズのあとは、squeue の表示を、GPU が働いている証拠にしないでください。ログが進んでいるか、nvidia-smi に学習のプロセスがあるかを確かめましょう。
10.4 小さな落とし穴あれこれ
パーティションの MaxTime を超える --time を付けると、ジョブはエラーにならず、PartitionTimeLimit を理由に PENDING のまま待ち続けます。静かに詰まるのでやっかいです
--time は上限であって、所要時間ではありません。8 時間の上限を付けたジョブが 2 時間で終わることもあるので、開始時刻の見積もりに使うとずれます
--output のパスは、スクリプトの中の cd より前に、sbatch を実行したディレクトリを基準に開かれます。絶対パスで書いておくと安心です
Slurm は VRAM を資源として扱わず、GPU が何枚空いているかしか見ません。画面表示に使っている GPU だと、ブラウザや VS Code も VRAM を使うので要注意です
11. おわりに
この記事では、まず GPU 1 枚で Kaggle の実験をするときに困ることを整理して、Slurm の導入と基本的な使い方を紹介しました。そのうえで、Claude Code や Codex と組み合わせるときの工夫、複数のコンペで 1 枚の GPU を分け合う方法、メモリの見積もり方、ハマりどころをまとめました。
キューに並べておけば GPU は夜のあいだも働いてくれますし、エージェントのセッションが切れても学習は続きます。導入も Claude や Codex に任せられるので、手元の GPU で Kaggle をしている方は、まず「Slurm を入れて」と頼むところから試してみてください!
参考文献
ymg_aq「手元のGPUを遊ばせないためのジョブスケジューラ入門」Tech Blog - Turing(Zenn)
Slurm: slurm.conf、sbatch、scontrol、Quality of Service (QOS)
Ray: Starting Ray、GCS Fault Tolerance、KubeRay の RocksDB による GCS の耐障害性
ray-project/ray issue #41437
Kubernetes: Creating a cluster with kubeadm
NVIDIA/k8s-device-plugin
Kueue Overview
sometimes i scroll thru cutlass issues to read wild bug reports cutlass#3797
45 likes · 1 repost · 1,779 views
Interactive World Simulation with Cosmos for Physical AI
We present a shared framework that adapts Cosmos world foundation models for real-time interactive world simulation in Physical AI. By streaming visual observations in response to actions and scene controls, the framework enables users and embodied agents to interact with evolving virtual environments. It supports both predicting the visual consequences of actions and generating observations from physical state maintained by an external simulator. We demonstrate this approach across camera navigation and robot manipulation, controllable video transfer, and multi-view autonomous vehicle (AV) simulation. These examples provide a shared foundation for developing interactive virtual environments for Physical AI training and evaluation. Our code and model checkpoints are available at nvidia/cosmos and huggingface.co. The project website is available at research.nvidia.com.
Comments: Project website: research.nvidia.com
NVIDIAのOSS「OpenShell」:自律AIエージェントを権限で閉じ込める実行環境
!海外の記事から
!🚀 上級者ワークフロー
📰 海外事例
元記事:OpenShell – A safe, private runtime for fleets of autonomous AI agents(github.com)
NVIDIA/OpenShell
---
!ざっくり概要
NVIDIAがGitHubで公開している OpenShell(Apache License 2.0)の紹介です。ファイルを読み、パッケージを入れ、APIを呼び、認証情報も使う自律型のAIエージェントを、データ・秘密情報・ネットワークへの無制限なアクセスなしに動かすための実行環境です。各エージェントが触れる範囲を「ポリシー」に宣言しておくと、OpenShellがそれを強制します。ここで紹介するのはREADMEに書かれた範囲で、実際には動かしていません。
<br>
!記事の要点
二つの守り方
一つ目はカーネルレベルの強制です。エージェントは隔離されたサンドボックスの中で動き、アクセスできるファイルと使えるシステムコール(OSへの命令)がカーネルの機能で絞られます。ネットワーク接続もすべて、外へ出る前にポリシーの検査を通ります。エージェントは本物の認証情報を見ることがなく、承認済みの宛先へ向かう通信にだけ、OpenShellが認証情報を付け足します。
二つ目は、ポリシー変更の形式検証です。ポリシーを変えて新しいホストへ認証情報つきで接続できるようになる、新しいAPIメソッドを呼べるようになる、といった危うい権限拡大を、承認の前に数学的な検証(形式検証)で見つけます。該当する変更は人の確認待ちになります。
使い始め
Linux、Apple SiliconのMac、WSL 2上のWindows(実験的)で動き、Docker・Podman・仮想化のいずれかが要ります。READMEのクイックスタートは、インストーラーを実行して openshell sandbox create --name demo を打つだけです。初期のサンドボックスはエージェントなしの最小のUbuntuで、実際のエージェントはチュートリアルで入れます。そこでは OpenCode を無料のOpenRouterモデルで動かし、エージェントが新しい権限を必要とするたびに承認していく流れが示されています。
周辺の仕組み
制御役のゲートウェイをKubernetes(コンテナを大量に管理する基盤)へ置く構成や、各言語の開発キット(SDK)も用意されています。
気をつけたい点
バージョンは0.1系で、公式が安定版の運用や新しい隔離機能を整えている途中です。また、匿名の利用統計を集める設定が標準で入っています。集めるのは操作の種別と回数だけで、サンドボックス名・ファイルパス・プロンプト・認証情報・モデル名は含まないと書かれています。止めたいときは環境変数 OPENSHELL_TELEMETRY_ENABLED=false を設定します。
<br>
!編集者のひとこと
自律エージェントで一番気をつけるのは、どこまで読ませて、どこまで動かさせるかだと思います。その封じ込めの環境をNVIDIAが用意しているのが面白い。
特に引かれたのは、OpenCodeを無料のOpenRouterモデルで動かす例です。無料モデルは入力が学習に使われるのが基本だと理解しているので、読ませてはいけない範囲は最初から閉じておきたい。OpenShellで封じ込めた状態から始めて、必要な権限だけ足していけば、初手で読み込まれすぎる事故は避けられる。そこがポイントかなと。
1 like
I got so much fucking swag even NVIDIA copying my shit
helixdb/helix-foundry
19 likes · 1 repost · 1,982 views
I had to go digging into the source to realize what it was, e.g.
github.com/NVIDIA/auto-ontology/blob/main/auto_on…
finally got to try nvidia openshell to sandbox my intern after having plugged off my dgx spark out of security scares
NVIDIA/OpenShell
will transfer to my dgx up next t.co
32 likes · 1 repost · 2,045 views
Nvidia – open-source auto-ontology | Discussion
2 likes
NVIDIA open-sourced Auto Ontology under Apache 2.0 🧩 It builds a semantic layer from enterprise metadata so AI agents write SQL against trusted business definitions, served over MCP, CLI and API.
#AI #AIAgents #OpenSource
NVIDIA/auto-ontology
4 likes
Flare, Nvidia's DGX Spark Inference Engine
2 points · 1 comment
Mentions
Slurm は Kaggle で役に立つ 1. はじめに Slurm は、スパコンや研究室の GPU クラスタでよく使われるジョブスケジューラです。投入されたジョブをキューに並べておいて、CPU・メモリ・GPU が空いたものから順に実行してくれます。 「大きなクラスタのための道具でしょ?」という印象がありますが、実は自宅の GPU 1 枚で Kaggle をするときにも、めちゃくちゃ役に立ちました!Kaggle の RSNA Knee Abnormality Detection(膝 MRI の異常検出)に RTX 3090 1 枚で参加したとき、学習ジョブの管理に Slurm を使っていたんです。41 日間で、RSNA の学習だけで 253 本のジョブを回して、GPU を延べ 469 時間も使いました。ここで紹介する方法は一般化してあるので、どんな GPU でも使えると思います!3090 は Kaggle で戦うにはつらいことは置いておいてくださいw Claude Code や Codex に実験を任せるなら、なおさらおすすめです。学習を Slurm に投げておけば、エージェントのセッションが切れても学習はそのまま走り続けてくれます。 3 行でいうと、こんな感じです。 GPU 1 枚のジョブキューなら、Ray や Kubernetes より入れるものが少なくて済みます。導入も Codex に任せたら約 25 分で終わりました 学習を Slurm に任せておけば、Claude Code や Codex のセッションが切れても学習は止まりません 別のコンペのジョブも同じキューに入れれば、1 枚の GPU を順番に分け合えます。優先度も変えられます Slurm のコマンドの基本は、Turing の ymg_aq さんの記事「手元のGPUを遊ばせないためのジョブスケジューラ入門」がとても丁寧にまとめてくれています。なのでこの記事では、Kaggle の実験で実際に使った設定と、エージェントと組み合わせるときの工夫を中心に紹介していきますね。 2. GPU 1 枚あるある まずは、自宅の GPU 1 枚で実験していて「うわ、困った…」となったことを並べてみます。 GPU がサボる。 学習が終わったことに気づかないと、次の実験を始めるまで GPU は止まったままです。「前のジョブが終わったら次を投入する」処理を tmux の sleep ループで書いたこともありますが、ループ自体がエラーも出さずに止まっていたことがありました。ひどい… エージェントが力尽きると、学習も道連れになる。 Claude Code などのバックグラウンドタスクで学習を動かしていると、セッションが終わったときに学習も止まっちゃいます。うっかりセッションを閉じてしまうこともありますし、Codex や Claude の利用上限でエージェントのループが止まることもありますよね 別のコンペと GPU を取り合う。 別のコンペの実験も同じ GPU で動かそうとすると、どっちが先に使うかを人間が調整することになります。メモリが足りなくなって、どちらかが強制終了されることもありました どれも、Slurm に任せるとかなり楽になりますよ! 3. Slurm とは Slurm は 2 つのデーモンで動いています。ジョブを受け付けて資源を割り当てる slurmctld と、実際にジョブを実行する slurmd です。munge は、この 2 つがお互いを認証するために使います。ジョブは、パーティションと呼ばれる投入先に sbatch コマンドで入れます。 もともとは多数のノードをまとめて管理するための道具ですが、1 台で使うなら、同じマシンで slurmctld と slurmd を動かすだけです。しかも、キューの状態は slurmctld が StateSaveLocation のディレクトリに保存してくれるので、デーモンを再起動してもキューは消えません! ちなみに Slurm には、終わったジョブの記録をデータベースに残す accounting という機能もあります。今回は入れていません。その代わりの工夫は 5.4 で紹介しますね。 4. 導入は Codex 任せで 25 分 「でも導入が大変なんでしょ?」と思ったあなた、安心してください。導入の手間は、ほとんど Claude や Codex が引き受けてくれます。 この章に載せている slurm.conf・gres.conf・cgroup.conf とセットアップスクリプトは、ぜんぶ Codex が書いたものです。私がやったのは sudo bash scripts/setup_slurm.sh を実行したことだけ!sudo が要る操作だけは自分で打ちます。入れると決めてから動くまで、約 25 分でした。slurm.conf の書き方を一から覚える必要もありません。 入れたあとも同じです。今の時代、Claude に「GPU のジョブは Slurm 経由で動かして」と頼めば、難しいジョブ定義を自分で書かなくても、いい感じに Slurm 経由にしてくれます! 使った環境はこんな感じです。 項目 内容 マシン 自宅のデスクトップ 1 台(Ubuntu 26.04.1 LTS) CPU / メモリ 10 コア 20 スレッド / 61GB。Slurm には 54,000MB として登録 GPU RTX 3090(24GB)1 枚。画面表示にも使用 Slurm Ubuntu のパッケージの slurm-wlm 25.11.2。accounting はなし セットアップスクリプトは、root 以外で実行すると止まるようにしてあります。それと、/etc/slurm/ に違う内容の設定ファイルがあるときは、上書きせずに止まります。 scripts/setup_slurm.sh #!/usr/bin/env bash Explicit host-admin setup. Never run the experiment controller as root. set -euo pipefail if [[ $EUID != 0 ]]; then echo 'Run on the host: sudo bash scripts/setup_slurm.sh' >&2 exit 1 fi if [[ $(hostname -s) != home-ubuntu ]]; then echo 'These configs target home-ubuntu; review the node configuration first.' >&2 exit 1 fi for name in slurm.conf gres.conf cgroup.conf; do if [[ -e /etc/slurm/$name ]] && ! cmp -s "ops/slurm/$name" "/etc/slurm/$name"; then echo "Existing /etc/slurm/$name differs; refusing to overwrite." >&2 exit 1 fi done apt-get update apt-get install -y slurm-wlm munge install -d -o slurm -g slurm /var/lib/slurm/slurmctld /var/lib/slurm/slurmd /var/log/slurm install -d -m 755 /etc/slurm for name in slurm.conf gres.conf cgroup.conf; do install -m 644 "ops/slurm/$name" "/etc/slurm/$name" done if [[ ! -s /etc/munge/munge.key ]]; then /usr/sbin/mungekey --create fi systemctl enable --now munge systemctl enable --now slurmctld slurmd slurmd -C slurmd -G scontrol ping sinfo -Nel 設定ファイルは次の 3 つです。リポジトリの ops/slurm/ に置いて、Git で管理しています。 ops/slurm/slurm.conf Single-node desktop configuration. CPU topology is checked against slurmd -C. ClusterName=rsna-local SlurmctldHost=home-ubuntu SlurmUser=slurm AuthType=auth/munge StateSaveLocation=/var/lib/slurm/slurmctld SlurmdSpoolDir=/var/lib/slurm/slurmd SlurmctldPidFile=/run/slurmctld.pid SlurmdPidFile=/run/slurmd.pid SlurmctldLogFile=/var/log/slurm/slurmctld.log SlurmdLogFile=/var/log/slurm/slurmd.log SelectType=select/cons_tres SelectTypeParameters=CR_Core_Memory SchedulerType=sched/backfill ProctrackType=proctrack/cgroup TaskPlugin=task/cgroup,task/affinity GresTypes=gpu ReturnToService=2 MinJobAge=86400 NodeName=home-ubuntu CPUs=20 Boards=1 SocketsPerBoard=1 CoresPerSocket=10 ThreadsPerCore=2 RealMemory=54000 Gres=gpu:1 State=UNKNOWN PartitionName=gpu Nodes=home-ubuntu Default=YES MaxTime=08:00:00 State=UP OverSubscribe=NO ops/slurm/gres.conf Manual GPU registration avoids a dependency on the NVML autodetection plugin. NodeName=home-ubuntu Name=gpu File=/dev/nvidia0 ops/slurm/cgroup.conf CgroupPlugin=autodetect ConstrainCores=yes ConstrainRAMSpace=yes ConstrainDevices=yes 設定のポイントはこのあたりです。 SelectType=select/cons_tres と CR_Core_Memory で、CPU コア・メモリ・GPU をジョブごとに別々に割り当てます cgroup.conf の 3 つの Constrain で、ジョブが要求した分を超える CPU・メモリ・GPU を使えないようにします gres.conf は、GPU を Slurm に登録するファイルです。NVIDIA の管理ライブラリ NVML による自動検出には頼らず、/dev/nvidia0 を手で書きました。ただ、これはカーネルを更新したときに裏目に出ます(10.2 で書きます) MinJobAge=86400 で、終わったジョブも 24 時間は scontrol で見られるようにしています。accounting の代わりですね ReturnToService=2 は、再起動したノードを自動で使える状態に戻す設定です パーティションは gpu の 1 つだけにして、1 ジョブの上限は 8 時間にしました 5. 基本的な使い方 ここからは、実験で実際に使ったコマンドを順に見ていきましょう! 5.1 sbatch でジョブを投入する sbatch でジョブを投げると、ジョブはキューに入ります。GPU が使われていれば、空くまで何時間でも待って、空いたらすぐ始まります。寝ている間も GPU に働いてもらえるのは、これのおかげです! GPU を使う学習の投入は、次のラッパースクリプトだけを使うことにしました。資源の要求(--gres=gpu:1、CPU 8 コア、メモリ 28G)をこの 1 か所に固定しておけば、GPU の指定を付け忘れる心配がありません。2 つ目の引数にジョブ ID を渡すと、そのジョブの後ろにつなげます(5.2 で説明します)。それと、再投入のたびにログのファイル名を attempt1.out、attempt2.out と変えるので、前の試行のログが上書きされることもありません。 scripts/gpu_submit.sh(コメントを省略) scripts/gpu_submit.sh <TAG> [afterany-jobid] [mem] set -euo pipefail cd "$(dirname "$0")/.." TAG="${1:?usage: gpu_submit.sh <TAG> [afterany-jobid]}" AFTER="${2:-}" MEM="${3:-28G}" JOB="runs/dino/$TAG/job.sh" [ -x "$JOB" ] || { echo "no executable $JOB" >&2; exit 1; } mkdir -p "runs/dino/$TAG/slurm" N=1; while [ -e "runs/dino/$TAG/slurm/attempt$N.out" ]; do N=$((N+1)); done DEP=() [ -n "$AFTER" ] && DEP=(--dependency="afterany:$AFTER") sbatch --parsable -p gpu --gres=gpu:1 -c 8 --mem="$MEM" -J "$TAG" \ -o "runs/dino/$TAG/slurm/attempt$N.out" "${DEP[@]}" "$JOB" 5.2 --dependency でジョブをつなぐ ジョブどうしの順番は、依存関係で決められます。sbatch に --dependency=afterany:<ジョブ ID> を付けて投げると、そのジョブは、指定したジョブが終わるまでキューの中で待ちます。afterany は、前のジョブが成功でも失敗でも、終わったら始まるタイプです。前のジョブが成功したときだけ始めたいなら、afterok を使います。 JOB1=$(sbatch --parsable train_a.sh) # --parsable を付けると、ジョブ ID だけが出力される sbatch --dependency=afterany:$JOB1 train_b.sh # JOB1 が終わったら、成否にかかわらず始める sbatch --dependency=afterok:$JOB1 eval_a.sh # JOB1 が成功したときだけ始める --parsable で受け取ったジョブ ID を次の投入に渡していけば、ジョブを何本でも数珠つなぎにできます。afterany なら、途中の 1 本が失敗しても後ろのジョブは止まりません。しかも依存関係は slurmctld が持っているので、tmux やエージェントのセッションが終わっても消えません。黙って止まる sleep ループとは、これでお別れです! ちなみに、優先度が同じなら、ジョブはだいたい投入順に始まります。ただ、必ずそうなるとは限りません。Slurm は、先頭のジョブの開始を遅らせない範囲で、後ろの小さなジョブを先に始めることがあるんです(backfill と呼びます)。順番が大事なジョブは、afterany でつないで明示しておくと安心ですよ。 5.3 squeue で予定表を見る squeue は、キューに入っているジョブの一覧を出すコマンドです。ジョブ名(-J)を実験のタグにしておくと、squeue の出力がそのまま実験の予定表になって便利です。 ただひとつ注意があります。Slurm は仕事はきっちりやってくれますが、報告はしてくれません。キューが空になれば GPU は止まったままですし、ジョブが終わったことも誰にも教えてくれないんです。私も、ジョブの完了に気づかずに GPU を約 10 時間空けてしまったことがあります…。 その対策として、次のジョブを常に 1 本、後ろに並べておくようにしました。さらに、squeue を監視する小さな常駐プログラムを作って、ジョブがキューから抜けたとき、残りが 1 本になったとき、キューが空になったときにだけ通知が来るようにしています。 5.4 scontrol show job で成否を確かめる accounting を入れていないので、終わったジョブの記録を調べる sacct は使えません。代わりに活躍するのが、ジョブやノードの状態を見たり変えたりできる scontrol です。slurm.conf に MinJobAge=86400 を書いて、終わったジョブも 24 時間は scontrol で見えるようにしています。 実験ループでは、squeue -h -j <ジョブ ID> が空になるまで待ってから、scontrol show job <ジョブ ID> -o を読みます。JobState=COMPLETED、ExitCode=0:0、結果ファイル cv.json の 3 つがそろったときだけ成功、というルールです。24 時間を過ぎると scontrol からも消えちゃうので、結果はループの状態ファイルに書いておきます。 5.5 scontrol update と --test-only で、待っているジョブを調整する 投入済みのジョブの資源は、投げ直さなくても変えられます。たとえばメモリの要求なら、scontrol update job=<ID> MinMemoryNode=28672 といった感じです。単位は MB なので、28G と書くと "Invalid MinMemoryNode value" で怒られます。ジョブ ID も依存関係もそのまま残るので、地味に便利です! ジョブがいつ始まりそうかは、sbatch --test-only で調べられます。同じ条件で --gres=gpu:1 の有無だけを変えて試すと、待っている原因がメモリなのか GPU なのかが分かりますよ。 5.6 scancel で取り消して、投入し直す Slurm は、投入されたバッチスクリプトの写しを、投入した時点で保存します。なので、投げたあとに job.sh を直しても、待っているジョブには反映されません。直したいときは、scancel で取り消して投げ直しましょう。bash -n の構文チェックでは、exec の行が消えたようなミスは見つからないので、書き込む前に中身を確かめておくのがおすすめです。 一方、Python のコードは、ジョブが始まったときに読まれます。予約したあとで train.py を直せば反映されますが、壊すと待っているジョブが全部失敗します。引数の検証も開始時にしか動かないので、投入する前に、その引数で検証だけ先に実行しておくと安心です。 6. Slurm × Claude Code / Codex ここからは、エージェントに実験を任せるときの使い方です。 6.1 セッションが力尽きても、学習は止まらない Slurm に投げた学習は、Slurm の管理下で動きます。投入したエージェントのプロセスとは関係がないので、Claude Code や Codex のセッションが切れても、利用上限でループが止まっても、学習は動き続けます! 実験ループの説明書にも、こう書いておきました。 チャットを閉じてもtmuxとSlurmの処理は続きます。マシンの停止・再起動は別です。 6.2 覚えておくのは、エージェントではなくリポジトリ 学習をエージェントから切り離すなら、「何を試して、結果がどうだったか」もエージェントの外に置いておく必要があります。Slurm が知っているのは、どのジョブが待っていて、どれが動いているかだけですからね。そこで、実験の状態はリポジトリのファイルに書いて、エージェントはそのファイルと squeue を読んで作業を続けるようにしました。 実験 1 本ごとに、省略なしのコマンドを runs/dino/<タグ>/job.sh に書きます。新しい実験は、実績のある job.sh の変数を 1 つだけ変えて作ります 学習ログの書式は、AGENTS.md(Claude Code や Codex が読む作業ルール)で決めています。先頭の行に START と設定と使うデバイスを書いて、30〜60 秒ごとに loss・速度・VRAM・残り時間を 1 行ずつ出します。最終行は必ず FINISHED か FAILED です。tqdm はキャリッジリターンのせいで tail -f で読めなくなるので、使いません 判断の経緯は ops/decisions.md に追記します AGENTS.md には「sbatch を手で書かない。投入は gpu_submit.sh だけ」と書いておきます エージェントが作業を再開するときの手順も、最初の項目を「squeue -h が空なら、既存の job.sh をコピーして 1 変数だけ変えた次の実験をすぐ投入する」にしておきました。 7. 複数のコンペで GPU を分け合う 7.1 同じパーティションに投入する 別のコンペのジョブも同じパーティションに入れておけば、Slurm が順番に GPU を割り当ててくれます。私の環境では、RSNA のほかに ARC Prize 2026 と、もう 1 つ別のプロジェクトのジョブも、同じ gpu パーティションに投げていました。優先度が同じなら投入順に始まるので、どっちが先に GPU を使うかを人間が調整する必要はありません! 自分のジョブを、別プロジェクトが最後に投げたジョブの後ろに afterany でつなぐ、という使い方もできます。相手が早く終わっても途中で失敗しても、すぐにこちらのジョブが始まるので、GPU が遊びません。 7.2 評価から集計まで、依存関係でまとめて予約する 依存関係を組み合わせると、次のようなジョブを 1 回のスクリプト実行でまとめて予約できます。 ベースモデルの評価 2 つの条件での学習 条件ごとの評価 集計と Discord への投稿 次のスクリプトは、ARC Prize 側で使った投入スクリプトから、ジョブの名前と中身を省いて、組み方だけを残したものです。 submit.sh(名前と中身を省略) common() { # ジョブ名, GPU を使うか(0/1), 制限時間。#SBATCH の行はすべて最初のコマンドより前に置く echo "#!/bin/bash" echo "#SBATCH -J $1 -p gpu -c 4 --mem=16G -t $3 -o $WORK/logs/%j-$1.out" if [ "$2" = 1 ]; then echo "#SBATCH --gres=gpu:1"; fi case "$1" in train-*) echo "#SBATCH --signal=B:TERM@300";; esac # 学習は SIGTERM を受けると resume.pt を保存する echo "set -euo pipefail; cd $REPO" } j1=$( { common eval-base 1 03:00:00; echo "<ベースモデルの評価>"; } | sbatch --parsable ) j2=$( { common train-a 1 08:00:00; echo "<条件 A の学習>"; } | sbatch --parsable ) j3=$( { common train-b 1 08:00:00; echo "<条件 B の学習>"; } \ | sbatch --parsable --dependency=afterok:$j1 --kill-on-invalid-dep=yes ) j4=$( { common eval-a 1 03:00:00; echo "<条件 A の評価>"; } \ | sbatch --parsable --dependency=afterok:$j2 --kill-on-invalid-dep=yes ) j5=$( { common eval-b 1 03:00:00; echo "<条件 B の評価>"; } \ | sbatch --parsable --dependency=afterok:$j3 --kill-on-invalid-dep=yes ) j6=$( { common report 0 00:10:00; echo "<集計と Discord への投稿>"; } \ | sbatch --parsable --dependency=afterany:$j4:$j5:$j1:$j2:$j3 --kill-on-invalid-dep=no ) ポイントはこのあたりです。 条件 B の学習はベースモデルの評価で作るファイルを使うので、afterok で評価の成功を待ちます。評価は学習が成功したときだけ実行して、集計は afterany で何があっても最後に実行します --kill-on-invalid-dep=yes を付けておくと、前のジョブが失敗して依存関係を満たせなくなったジョブを、Slurm がキューから消してくれます --signal=B:TERM@300 は、制限時間の 300 秒前に、バッチスクリプトのシェルへ SIGTERM を送る指定です。学習側は SIGTERM を受けると resume.pt を保存します 集計ジョブは GPU を使わないので、--gres を付けずに CPU だけのジョブにしています #SBATCH の行を含むスクリプトを関数の出力として組み立てて、標準入力から sbatch に渡しています。ちょっとトリッキーですが、意外と快適です 7.3 優先度を変える(未検証) コンペごとに優先度を変えたいときの手段は、次のとおりです。今回は使っていないので、Slurm のドキュメントで調べた内容になります。 sbatch --nice=100 や scontrol update job=<ID> nice=100 で、ジョブの優先度を下げられます。負の値で優先度を上げられるのは、特権ユーザーだけです(sbatch、scontrol) scontrol top <ID> で、同じユーザー・パーティション・アカウント・QOS のジョブの中で、指定したジョブを先頭に移せます。QOS は、ジョブの種類ごとに優先度や上限を決める設定のことです。一般ユーザーには既定で無効なので、slurm.conf に SchedulerParameters=enable_user_top を書く必要があります root なら、scontrol update job=<ID> priority=<値> で優先度を直接決められます。決めた値は固定されて、優先度プラグインは更新しなくなります。プラグインに戻すには、ジョブを hold してから release します コンペごとにパーティションを分けて PriorityTier を変える方法や、QOS を分ける方法もあります 空いた時間にだけ別の実験を入れたい場合は、優先度の高いジョブのために実行中のジョブを止める preemption という機能もあります。こちらも試していないので、私は投入の前後に条件を確かめる仕組みを自作しました。投げる前に、他のジョブがないこと、nvidia-smi に計算プロセスがないこと、メモリとディスクの空きが足りていることをチェックします。メインの実験が GPU を必要としたら、学習側が自分から終了してくれる作りです。 8. メモリをジョブごとに区切る cgroup.conf で設定しておくと、Slurm は、ジョブが要求した分を超える CPU・メモリ・GPU を、cgroup(Linux の資源制限の仕組み)で使えなくしてくれます。GPU を要求しなかったジョブからは、GPU が見えません。 これが特に効いてくるのが、メモリが足りなくなったときです。以前、tmux で動かしていた前処理(8 workers、22GB)が、systemd-oomd にユーザーのスコープごと強制終了されたことがありました。ところが、同時に Slurm で動いていた学習は無事だったんです!Slurm のジョブは、systemd-oomd が監視しているユーザーのスコープの外で動いているからですね。それからは、重い前処理にも --mem を付けて Slurm に投げるようにしています。 ただし、Slurm が数えるのは自分のジョブのメモリだけです。Slurm の外で動かしたプロセスの分は数えてくれないので、ジョブの横で大きな処理を動かすと、OOM killer に止められることがあります。そこは気をつけてください。 8.1 GPU ジョブどうしは、メモリを減らしても同時には動かない GPU が 1 枚なら、GPU を要求するジョブどうしは、メモリ要求をいくら減らしても同時には動きません。メモリの合計が問題になるのは、GPU ジョブの横で、--gres を付けない CPU だけのジョブ(前処理や集計)を動かすときです。 ノードに登録したメモリは 54,000MB です。たとえば学習ジョブが --mem=40G だと、別のコンペの --mem=16G のジョブは横で動けません。40 + 16 が 54 を超えちゃうからです。 8.2 メモリ要求は、memory.peak ではなく anon と shmem で見積もる では、学習ジョブに本当に必要なメモリはどれくらいなんでしょうか。実行中のジョブの cgroup のファイルを直接読むと分かります。 CG=/sys/fs/cgroup/system.slice/home-ubuntu_slurmstepd.scope/job_<ジョブ ID> cat $CG/memory.peak # 33.9GB grep -E '^(anon|shmem) ' $CG/memory.stat # anon 4.5G、shmem 6.2G cat $CG/memory.events # high 0 max 0 oom 0 oom_kill 0 コメントの値は、ある学習ジョブで測ったものです。memory.peak は 33.9GB で、数字だけ見るとかなりの大食いですよね。でも、このうち解放できないのは、プロセスが確保したメモリ(anon)と共有メモリ(shmem)で、合わせて約 11GB だけでした!残りは、mmap で読んでいる画像キャッシュがページキャッシュとして載っていた分で、必要になればいつでも解放できます。memory.events を見ても、制限には一度も近づいていません。 そこで、既定を 28G に下げました。28 + 16 = 44 なので、別のコンペの CPU ジョブも横で動けます。ただし、注意点が 3 つあります。 メモリの上限が小さい cgroup ほどページキャッシュが強く回収されるので、下げたあとは 1 step あたりの時間が遅くなっていないかを確かめましょう 学習中より評価中のほうがメモリを使う構成もあります。28G では、学習のあとの推論の途中で OOM killer に強制終了されたモデルがあって、そのモデルは 36G にしました。測るなら、評価まで含めて測るのがおすすめです cgroup はジョブが終わると消えちゃうので、実行中に一定の間隔で値を記録しておきましょう OOM で強制終了されたときは、学習ログには traceback も FINISHED も出ません。slurmd のログにだけ、次のような行が残ります。 error: Detected 4 oom_kill events in StepId=280.batch. 9. Ray や Kubernetes じゃだめなの? ! Ray と Kubernetes は今回試していません。この章は、ドキュメントと issue を読んで比べた内容です。 だめではないんです。ただ、GPU 1 枚のジョブキューとして使うには、どちらも Slurm より手間がかかります。しかも、手間のかかり方が 2 つでかなり違うんですよね。 9.1 Kubernetes は、まずクラスタを組むところから いちばん大きな差は、Kubernetes だとクラスタの構築から始めることになる点です。Kubernetes は、複数のノードでクラスタを組む前提で作られています。kubeadm で組む場合、既定ではコントロールプレーン(クラスタを管理するノード)に Pod を載せません。1 台で動かすには、この制限(taint)を外す手順が要ります(kubeadm のドキュメント)。Pod どうしが通信するためのネットワークアドオン(CNI)も入れる必要があって、入れるまではクラスタ内の DNS(CoreDNS)も起動しません。 GPU を使うには、さらに NVIDIA の device plugin が要ります。その前提として、nvidia-container-toolkit を入れて、nvidia-container-runtime をコンテナの既定のランタイムに設定します。学習コードも、コンテナイメージにまとめることになります。ジョブを待たせて順に実行したければ、そのうえで Kueue のような、ジョブの受け入れを管理する仕組みも入れます。 k3s や minikube のような 1 台向けの配布版を使えば構築は楽になりますが、device plugin やコンテナイメージ、Kueue が要るのは変わりません。Kaggle の学習を 1 台で順番に回したいだけなのに、やることが多すぎます…。 9.2 Ray は 1 台でもすぐ動くが、キューとしては物足りない Ray は事情がちょっと違います。Ray のドキュメントには、ノートパソコンでも 1 台のサーバーでも動かせると書いてあって、ray start --head で 1 ノードの Ray が立ち上がります。pip で入るし、root 権限も要りません。インストールの手軽さなら、Ray のほうが上です。Slurm は apt で入れるものの sudo が必要で、munge の鍵や cgroup の設定もありますからね。 でも、Ray との差が出るのは、夜のうちにジョブを何本も並べておく、キューとしての使い方なんです。 1 つ目は、キューが残るかどうか。Slurm は、キューの状態を StateSaveLocation のディレクトリに保存します(slurm.conf)。Ray では、クラスタの状態を持つ GCS(Global Control Service)が、既定ではすべてをメモリに置きます。Ray のドキュメントによると、GCS が止まるとクラスタ全体が止まります。状態を残したければ、外部の Redis か、alpha 版の RocksDB バックエンドが必要です。 2 つ目は、開始をどれだけ待てるか。Ray Jobs でも、エントリーポイントに GPU を予約して投げれば、GPU が空くまで開始を待ってくれます。ただ、この開始待ちにはタイムアウトがあります。issue #41437 では、ジョブが「Job supervisor actor failed to start within 900.0 seconds.」というエラーで失敗しています。上限は RAY_JOB_START_TIMEOUT_SECONDS で変えられますが、大きくしておかないと、前のジョブが何時間も GPU を使っている間に、後ろのジョブが開始待ちのまま失敗しちゃいます。Slurm のジョブは、資源が空くまで何時間でも待ってくれます。 3 つ目は、ジョブどうしの依存関係。Slurm なら --dependency=afterany:<ジョブ ID> と書くだけです。 9.3 1 台なら、Slurm がいちばん入れるものが少ない というわけで、GPU 1 枚でジョブキューが欲しいなら、Ray や Kubernetes より Slurm のほうが入れるものが少なく済む、というのが私の結論です。Slurm もクラスタ向けの道具ですが、1 台なら、デーモン 2 つと munge、設定ファイル 3 つで動きます。ただし、保守の手間はかかります。10.2 のように、カーネルを更新したあとに sudo で直す場面もありました。 10. ハマりどころ 最後に、運用中にハマったところをまとめておきます。同じ轍を踏まないでくださいね…! 10.1 --gres=gpu:1 を忘れると、GPU を使えない GPU ジョブになる --gres=gpu:1 を付けずに投げたジョブにも、Slurm は CPU とメモリだけを割り当てて、普通に開始します。cgroup の ConstrainDevices=yes で GPU が見えなくなるので、学習は数秒で "CUDA unavailable" と言って止まります。私の環境では、afterany でつないだ後ろのジョブも同じように止まって、GPU が 2.4 時間空いてしまいました。 紛らわしいのは、scontrol show job の ReqTRES=cpu=8,mem=40G,node=1,billing=8 の欄に、GPU の要求(gres)が出ないことです。この欄を写して sbatch を手で書くと、GPU の指定が抜けます。投入をラッパースクリプトにまとめたのは、これが理由でした。 ! ジョブが GPU を持っているかは、ReqTRES ではなく、scontrol show job の TresPerNode=gres/gpu:1 か、scontrol show node -d の GresUsed=gpu:1 で確かめてください。ReqTRES に GPU がなくても、GPU を要求していないとは限りません。 再投入したあとは、新しいログに device=NVIDIA GeForce RTX 3090 free=21.47GiB のような行が出たのを確かめるまで、直ったとは見なさないようにしています。 10.2 カーネルを更新したら、slurmd が起きてこない カーネルが上がったのに、NVIDIA のカーネルモジュールが古いカーネル向けしか入っていないと、/dev/nvidia0 ができません。gres.conf に /dev/nvidia0 を手で書いていると、slurmd は gres.conf を読むところでエラーになって、起動しなくなります。 slurmd[4420]: fatal: can't stat gres.conf file /dev/nvidia0: No such file or directory こうなると、sinfo はノードを down*(停止して応答しない状態)と表示しますし、学習中だったジョブは失われます。復旧には sudo が要ります。私の環境では、次のコマンドで戻りました。 sudo apt install -y linux-modules-nvidia-595-open-7.0.0-38-generic \ && sudo modprobe nvidia && nvidia-smi \ && sudo systemctl restart slurmd \ && sudo scontrol update nodename=home-ubuntu state=resume カーネルの自動更新を止めるか、再起動のあとに nvidia-smi と sinfo を確かめる習慣をつけておくといいと思います。 10.3 止まったジョブが、まだ RUNNING だと言い張る マシンがフリーズして戻ってきたあと、学習のプロセスはもうないのに、Slurm が JobState=RUNNING を返し続けたことがありました。nvidia-smi を見ても、デスクトップ画面の分しか出ていません。 ! 再起動やフリーズのあとは、squeue の表示を、GPU が働いている証拠にしないでください。ログが進んでいるか、nvidia-smi に学習のプロセスがあるかを確かめましょう。 10.4 小さな落とし穴あれこれ パーティションの MaxTime を超える --time を付けると、ジョブはエラーにならず、PartitionTimeLimit を理由に PENDING のまま待ち続けます。静かに詰まるのでやっかいです --time は上限であって、所要時間ではありません。8 時間の上限を付けたジョブが 2 時間で終わることもあるので、開始時刻の見積もりに使うとずれます --output のパスは、スクリプトの中の cd より前に、sbatch を実行したディレクトリを基準に開かれます。絶対パスで書いておくと安心です Slurm は VRAM を資源として扱わず、GPU が何枚空いているかしか見ません。画面表示に使っている GPU だと、ブラウザや VS Code も VRAM を使うので要注意です 11. おわりに この記事では、まず GPU 1 枚で Kaggle の実験をするときに困ることを整理して、Slurm の導入と基本的な使い方を紹介しました。そのうえで、Claude Code や Codex と組み合わせるときの工夫、複数のコンペで 1 枚の GPU を分け合う方法、メモリの見積もり方、ハマりどころをまとめました。 キューに並べておけば GPU は夜のあいだも働いてくれますし、エージェントのセッションが切れても学習は続きます。導入も Claude や Codex に任せられるので、手元の GPU で Kaggle をしている方は、まず「Slurm を入れて」と頼むところから試してみてください! 参考文献 ymg_aq「手元のGPUを遊ばせないためのジョブスケジューラ入門」Tech Blog - Turing(Zenn) Slurm: slurm.conf、sbatch、scontrol、Quality of Service (QOS) Ray: Starting Ray、GCS Fault Tolerance、KubeRay の RocksDB による GCS の耐障害性 ray-project/ray issue #41437 Kubernetes: Creating a cluster with kubeadm NVIDIA/k8s-device-plugin Kueue Overview
sometimes i scroll thru cutlass issues to read wild bug reports cutlass#3797
Interactive World Simulation with Cosmos for Physical AI We present a shared framework that adapts Cosmos world foundation models for real-time interactive world simulation in Physical AI. By streaming visual observations in response to actions and scene controls, the framework enables users and embodied agents to interact with evolving virtual environments. It supports both predicting the visual consequences of actions and generating observations from physical state maintained by an external simulator. We demonstrate this approach across camera navigation and robot manipulation, controllable video transfer, and multi-view autonomous vehicle (AV) simulation. These examples provide a shared foundation for developing interactive virtual environments for Physical AI training and evaluation. Our code and model checkpoints are available at nvidia/cosmos and huggingface.co. The project website is available at research.nvidia.com. Comments: Project website: research.nvidia.com
NVIDIAのOSS「OpenShell」:自律AIエージェントを権限で閉じ込める実行環境 !海外の記事から !🚀 上級者ワークフロー 📰 海外事例 元記事:OpenShell – A safe, private runtime for fleets of autonomous AI agents(github.com) NVIDIA/OpenShell --- !ざっくり概要 NVIDIAがGitHubで公開している OpenShell(Apache License 2.0)の紹介です。ファイルを読み、パッケージを入れ、APIを呼び、認証情報も使う自律型のAIエージェントを、データ・秘密情報・ネットワークへの無制限なアクセスなしに動かすための実行環境です。各エージェントが触れる範囲を「ポリシー」に宣言しておくと、OpenShellがそれを強制します。ここで紹介するのはREADMEに書かれた範囲で、実際には動かしていません。 <br> !記事の要点 二つの守り方 一つ目はカーネルレベルの強制です。エージェントは隔離されたサンドボックスの中で動き、アクセスできるファイルと使えるシステムコール(OSへの命令)がカーネルの機能で絞られます。ネットワーク接続もすべて、外へ出る前にポリシーの検査を通ります。エージェントは本物の認証情報を見ることがなく、承認済みの宛先へ向かう通信にだけ、OpenShellが認証情報を付け足します。 二つ目は、ポリシー変更の形式検証です。ポリシーを変えて新しいホストへ認証情報つきで接続できるようになる、新しいAPIメソッドを呼べるようになる、といった危うい権限拡大を、承認の前に数学的な検証(形式検証)で見つけます。該当する変更は人の確認待ちになります。 使い始め Linux、Apple SiliconのMac、WSL 2上のWindows(実験的)で動き、Docker・Podman・仮想化のいずれかが要ります。READMEのクイックスタートは、インストーラーを実行して openshell sandbox create --name demo を打つだけです。初期のサンドボックスはエージェントなしの最小のUbuntuで、実際のエージェントはチュートリアルで入れます。そこでは OpenCode を無料のOpenRouterモデルで動かし、エージェントが新しい権限を必要とするたびに承認していく流れが示されています。 周辺の仕組み 制御役のゲートウェイをKubernetes(コンテナを大量に管理する基盤)へ置く構成や、各言語の開発キット(SDK)も用意されています。 気をつけたい点 バージョンは0.1系で、公式が安定版の運用や新しい隔離機能を整えている途中です。また、匿名の利用統計を集める設定が標準で入っています。集めるのは操作の種別と回数だけで、サンドボックス名・ファイルパス・プロンプト・認証情報・モデル名は含まないと書かれています。止めたいときは環境変数 OPENSHELL_TELEMETRY_ENABLED=false を設定します。 <br> !編集者のひとこと 自律エージェントで一番気をつけるのは、どこまで読ませて、どこまで動かさせるかだと思います。その封じ込めの環境をNVIDIAが用意しているのが面白い。 特に引かれたのは、OpenCodeを無料のOpenRouterモデルで動かす例です。無料モデルは入力が学習に使われるのが基本だと理解しているので、読ませてはいけない範囲は最初から閉じておきたい。OpenShellで封じ込めた状態から始めて、必要な権限だけ足していけば、初手で読み込まれすぎる事故は避けられる。そこがポイントかなと。
I got so much fucking swag even NVIDIA copying my shit helixdb/helix-foundry
I had to go digging into the source to realize what it was, e.g. github.com/NVIDIA/auto-ontology/blob/main/auto_on…
finally got to try nvidia openshell to sandbox my intern after having plugged off my dgx spark out of security scares NVIDIA/OpenShell will transfer to my dgx up next t.co
Nvidia – open-source auto-ontology | Discussion
NVIDIA open-sourced Auto Ontology under Apache 2.0 🧩 It builds a semantic layer from enterprise metadata so AI agents write SQL against trusted business definitions, served over MCP, CLI and API. #AI #AIAgents #OpenSource NVIDIA/auto-ontology
Flare, Nvidia's DGX Spark Inference Engine