zxell.ai
開発記録 / review24
この記録は、プロジェクトの作業報告(報告 → アーキテクトの回答)を公開用に編集したものです。サーバ運用・セキュリティに関わる部分を省略しています(編集方針)。

review24: RTX 3060 機の立ち上げ完了 — ドライバ・PyTorch・クライアント承認・シャード取得・S 動作確認(39,900 トークン/秒)。OOM と評価サンプリングの 2 件を修正し、S ベースライン本番(約 21 時間)の起動へ

作成日: 2026-10-06 対象: review23 の手順書 5-1〜5-5 の実施結果と、その過程で見つかった不具合 2 件の修正。

要旨

  1. 3060 機は学習可能な状態になりました。 ドライバ 595.91.07(CUDA 13.2 対応)、PyTorch cu128、クライアント rtx3060 の登録・承認、シャード 124 個の API 経由取得まで完了(1〜2 章)
  2. S 構成の動作確認で 39,900 トークン/秒(見積り 35,000〜40,000 の上限側)。30 ステップで loss 10.86 → 7.91(3 章)
  3. 途中で CUDA OOM(語彙 48k の logits が fp32 で 5.9GB)→ 損失計算をチャンク化+再計算方式に修正。一括計算と損失・勾配が一致することを検証済み(4 章)
  4. 途中評価が val の先頭しか見ず 1 言語しか出ない問題 → val 全体から等間隔に窓を取る方式に修正(5 章)
  5. 本番(90,000 ステップ ≈ 2.95B トークン、約 21 時間)の起動コマンドを提示済み(6 章)。起動後 500 ステップ目の評価行を見て健全性を確認します

1. 3060 機のセットアップ結果(review23 5-1〜5-4)

手順結果
5-1 ドライバubuntu-drivers install で 595.91.07 が導入。nvidia-smi で RTX 3060 / 12,288 MiB を認識。CUDA Version 表示は 13.2
5-2 PyTorchcu128 ホイールで導入(ドライバの「CUDA 13.2」は上限表示であり、12.8 ランタイムは後方互換で動く — 手順変更なし)
5-3 登録・承認クライアント rtx3060 を登録 → サーバで承認 → approved
5-4 シャード取得fetch_shards.py で 124 シャード + メタ + 言語副ファイル(計 251 ファイル)を LAN 経由で取得、sha256 照合つき

これでクライアント登録済みは 2 台: (省略: ホスト名)(GTX 1050 / Windows、フェーズ 2 で参加)と rtx3060。

2. ドライバの CUDA 版についてのご質問

CUDA のバージョンは 13.2 でした。インストールするドライバが変わってきますか?

変わりません。nvidia-smi の「CUDA Version」はそのドライバが対応できる CUDA の上限で、CUDA ツールキットは入れていません(不要)。 PyTorch のホイールは CUDA ランタイムを同梱しており、新しいドライバは古いランタイムを後方互換で動かします。 cu128 のまま導入し、torch.cuda.is_available() が True になりました。

3. S 構成の動作確認(30 ステップ)

preset S: 29.1M params (10.6M non-embedding), ctx 1024, device cuda
step  1  loss 10.857  tok/s 33,535
step 10  loss  9.178  tok/s 39,497
step 20  loss  8.213  tok/s 39,833
step 30  loss  7.907  tok/s 39,897
val(先頭 20 万トークン): PPL 4,858   ← 30 ステップ時点。初期値(一様)は 48,000

4. 修正 1: CUDA OOM(コミット c280eab)

原因

損失計算で logits(32 × 1024 × 48,000)を fp32 に展開すると 1 回で 5.9GB。bf16 でも 3.1GB。モデル本体(重み+勾配+optimizer)は 0.5GB 程度なので、語彙の大きさが S モデルのメモリの支配項でした(review22 2 章の「S は埋め込みが大半」がメモリでも効いた形)。

対処

LM Head と cross-entropy を 4 シーケンスずつのチャンクで計算し、torch.utils.checkpoint で逆伝播時に再計算する方式に変更。同時に保持する logits は 1/8 になり、計算量の増加は LM Head の再計算分だけ(Transformer 本体に比べ小さい)。学習時は logits を返さず損失だけ返す(評価時は従来どおり logits を返す)。

検証

5. 修正 2: 途中評価が 1 言語しか見ない(コミット c13ff4d)

原因

途中評価(500 ステップごと、val 先頭 100 万トークン)は先頭から取る仕様でした。val は走査順で、同じチャンネルの記事が id 順に固まっているため、先頭 20 万トークンはすべてフランス語でした(3 章の fr のみの表示)。

対処

トークン数で制限するときは val 全体から等間隔に窓を選ぶ方式に変更。30 万トークン分の窓で en 61% / de 14% / fr 14% / ja 11% と、val 全体の構成どおりに 4 言語が入ることを確認。最終評価(全量)は変更なし。

6. 本番の起動(提示済み)

cd ~/zxell/zxell_model && . .venv/bin/activate && git pull
tmux new -s zxell
python train.py --preset S --shards ~/zxell-shards --out runs/S_baseline --steps 90000 2>&1 | tee runs/S_baseline/stdout.log
項目値
ステップ数90,000(batch 32 × ctx 1024 = 32,768 トークン/ステップ)
総トークン2.95B(train 6.07B の約半分、1 エポック未満。roadmap 3.3 の S: 3B)
所要約 20.5 時間 + 途中評価(180 回 × 数秒〜十数秒)≈ 21 時間
途中評価500 ステップごとに val 100 万トークン(等間隔サンプル)の言語別 PPL
最終評価val 全量(1,020 万トークン)の言語別 PPL
チェックポイント1,000 ステップごと ckpt_last.pt(上書き)、終了時 ckpt_final.pt。中断時は --resume で再開
ハイパーパラメータlr 6e-4、warmup 500、cosine → 6e-5、AdamW(β 0.9/0.95、wd 0.1)、勾配クリップ 1.0、bf16

起動後の確認ポイント: 500 ステップ目の "eval" 行(起動約 7 分後)で 4 言語とも PPL が出て、いずれも初期値(≈48,000)から大きく下がっていること。その後は 1 日放置で問題ありません。

7. 本日のコミット

コミット内容
c280eab損失計算のチャンク化 + checkpoint(OOM 対策)
c13ff4d評価窓の等間隔サンプリング

(review23 までの zxell_model 本体: 23a4c97、4ecfac2)

8. 確認事項

  1. 本番の起動(6 章)をお願いします。500 ステップ目の評価行が出たら、その前後数行を貼ってください。
  2. 学習中、3060 機は他の用途に使っても構いません(VRAM に余裕あり)が、GPU を使う別処理は避けてください(速度が落ち、見積りが狂います)。
  3. 学習完了後の評価(test の言語別 PPL・生成サンプル)と、フェーズ 1 の完了判定はこちらで行い、review で報告します。

9. 次の作業予定

  1. S ベースライン学習(約 21 時間)の見守り: 500 ステップ目の健全性確認 → 途中経過(損失曲線・言語別 PPL の推移)の可視化
  2. 学習完了後: eval.py で test の言語別 PPL、sample.py で生成サンプル(4 言語)→ フェーズ 1 の完了判定(review25 で報告)
  3. フェーズ 2 の設計着手: クライアント v1 の train タスクを本物の局所学習(zxell_model 呼び出し)に置き換える、 1050 向けのトークン範囲タスク、サーバ側の Δ 集約(FedAvg)
← review23目次review25 →