Skip to content

Commit 0603b87

Browse files
Merge pull request #3816 from AI-Hypercomputer:agagik-xpk
PiperOrigin-RevId: 910903295
2 parents 661a153 + 9d0298a commit 0603b87

3 files changed

Lines changed: 67 additions & 17 deletions

File tree

docs/tutorials/posttraining/knowledge_distillation.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ Then:
381381
# One-time: layer Tunix on top of the MaxText base image
382382
bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh prep_image
383383
384+
# Bake ./src into a runner image and push to gcr.io/$XPK_PROJECT/...:${USER}-distill
385+
bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh upload_runner
386+
384387
# Submit a workload
385388
bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh submit
386389

src/maxtext/trainers/post_train/distillation/README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,15 @@ If `can-i` prints `no`, ask a cluster admin to bind
6868
## 4. Build + push the image (one time)
6969

7070
The flow is: build the MaxText base → `prep_image` rebuilds `$XPK_BASE_IMAGE`
71-
**in place** (same local tag) with tunix layered on top → `docker_upload_runner.sh`
72-
pushes that modified local tag to GCR under `$CLOUD_IMAGE_NAME`.
71+
**in place** (same local tag) with tunix layered on top → `upload_runner`
72+
bakes the workspace `./src` into a runner image and pushes it to GCR.
7373

7474
```bash
75-
# Local tag prep_image rebuilds; registry name docker_upload_runner pushes to.
76-
export XPK_BASE_IMAGE=maxtext_base_image:stable
77-
export CLOUD_IMAGE_NAME=gcr.io/<your-project>/maxtext_base_image:stable
75+
export XPK_PROJECT=<your-project>
76+
export XPK_BASE_IMAGE=maxtext_base_image # local tag prep_image rebuilds
77+
export XPK_RUNNER_IMAGE_NAME=maxtext_base_image # short name pushed under gcr.io/$XPK_PROJECT/
78+
# XPK_RUNNER_IMAGE_TAG defaults to ${USER}-distill; override (or set USER)
79+
# if your shell $USER produces an awkward tag, e.g. XPK_RUNNER_IMAGE_TAG=agagik-distill.
7880

7981
# Base image with MaxText + TPU deps.
8082
sudo bash src/dependencies/scripts/docker_build_dependency_image.sh \
@@ -83,19 +85,24 @@ sudo bash src/dependencies/scripts/docker_build_dependency_image.sh \
8385
# Layer tunix + re-pin jax/libtpu for libtpu compat. Rebuilds $XPK_BASE_IMAGE in place.
8486
bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh prep_image
8587

86-
# Push the modified local tag to GCR so later submits pull from the registry (no buildx).
87-
sudo bash src/dependencies/scripts/docker_upload_runner.sh \
88-
CLOUD_IMAGE_NAME=${CLOUD_IMAGE_NAME}
88+
# Bake ./src into the layered image and push to
89+
# gcr.io/$XPK_PROJECT/$XPK_RUNNER_IMAGE_NAME:$XPK_RUNNER_IMAGE_TAG.
90+
bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh upload_runner
8991
```
9092

93+
The runner image copies the local workspace into `/deps/src/maxtext/`, so any
94+
edits in your checkout ship with the image without a rebuild of the base.
95+
The submit command's `PYTHONPATH=/deps/src:/app/src` covers both the runner-baked
96+
layout and xpk's crane-overlay fallback.
97+
9198
## 5. Submit
9299

93100
```bash
94101
export XPK_CLUSTER=<cluster>
95102
export XPK_PROJECT=<project>
96103
export XPK_ZONE=<zone>
97104
export XPK_DEVICE_TYPE=tpu7x-4x4x4
98-
export XPK_BASE_IMAGE=${CLOUD_IMAGE_NAME} # slash in name → --docker-image auto-selected
105+
export XPK_BASE_IMAGE=gcr.io/${XPK_PROJECT}/${XPK_RUNNER_IMAGE_NAME}:${XPK_RUNNER_IMAGE_TAG:-${USER}-distill} # slash → --docker-image auto-selected
99106
export XPK_BASE_OUTPUT_DIR=gs://<bucket>/distillation
100107
export XPK_RUN_NAME=<experiment> # default: distill_run; set per experiment
101108
# to scope checkpoints + TB under

src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#
3030
# Usage:
3131
# bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh prep_image # one-time image layering
32+
# bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh upload_runner # bake workspace + push to GCR
3233
# bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh submit # fire-and-forget; returns in ~60s
3334
# bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh monitor # stream logs for the last submit
3435
# bash src/maxtext/trainers/post_train/distillation/scripts/run_distill_xpk.sh resume_until_done # auto-retry loop for long jobs
@@ -102,9 +103,18 @@
102103
# default: git+https://github.com/google/tunix@110932a8395086511228483312131841521695c1
103104
# Use "google-tunix==<ver>" once a pypi release ships with the
104105
# multi-host shard_input fix.
105-
# JAX_PIN default: 0.9.2 — version to pin back after tunix deps resolve.
106-
# JAXLIB_PIN default: 0.9.2
107-
# LIBTPU_PIN default: 0.0.37
106+
# JAX_PIN default: 0.10.0 — version to pin back after tunix deps resolve.
107+
# Must be ≥ 0.10.0 (tunix's flax dep imports jax.extend.core.Effect).
108+
# JAXLIB_PIN default: 0.10.0
109+
# LIBTPU_PIN default: 0.0.39
110+
#
111+
# upload_runner env vars:
112+
# XPK_RUNNER_IMAGE_NAME default: maxtext_base_image — GCR short name.
113+
# XPK_RUNNER_IMAGE_TAG default: ${USER}-distill — per-user tag avoids
114+
# clobbering shared :latest. Override (or set USER) if
115+
# your shell $USER produces an awkward tag, e.g.
116+
# XPK_RUNNER_IMAGE_TAG=agagik-distill. Pushes to
117+
# gcr.io/$XPK_PROJECT/$XPK_RUNNER_IMAGE_NAME:$XPK_RUNNER_IMAGE_TAG.
108118
#
109119
# Resume on failure:
110120
# `resume_until_done` reuses the same XPK_BASE_OUTPUT_DIR/XPK_WORKLOAD across
@@ -149,9 +159,9 @@ require_env() {
149159

150160
# Image pinning (used by prep_image).
151161
: "${TUNIX_SOURCE:=git+https://github.com/google/tunix@110932a8395086511228483312131841521695c1}"
152-
: "${JAX_PIN:=0.9.2}"
153-
: "${JAXLIB_PIN:=0.9.2}"
154-
: "${LIBTPU_PIN:=0.0.37}"
162+
: "${JAX_PIN:=0.10.0}"
163+
: "${JAXLIB_PIN:=0.10.0}"
164+
: "${LIBTPU_PIN:=0.0.39}"
155165

156166
# Computed at top-level so both submit_workload and resume_until_done can read it.
157167
# `${:-}` keeps `set -u` happy for `prep_image`, which doesn't need XPK_BASE_OUTPUT_DIR.
@@ -225,6 +235,31 @@ print(f'tunix {tunix.__version__}: shard_input fix present.')
225235
"
226236
}
227237

238+
# -------------------------- upload_runner --------------------------
239+
# Bakes ./src into the layered image and pushes to
240+
# gcr.io/$XPK_PROJECT/$XPK_RUNNER_IMAGE_NAME:$XPK_RUNNER_IMAGE_TAG.
241+
# Does the build/tag/push inline rather than calling docker_upload_runner.sh,
242+
# because that script hardcodes :latest and would clobber the shared tag.
243+
upload_runner() {
244+
: "${XPK_RUNNER_IMAGE_NAME:=maxtext_base_image}"
245+
: "${XPK_RUNNER_IMAGE_TAG:=${USER}-distill}"
246+
local target="gcr.io/${XPK_PROJECT}/${XPK_RUNNER_IMAGE_NAME}:${XPK_RUNNER_IMAGE_TAG}"
247+
echo "== upload_runner -> ${target} =="
248+
if ! sudo docker image inspect "$XPK_BASE_IMAGE" >/dev/null 2>&1; then
249+
echo "ERROR: base image $XPK_BASE_IMAGE not found locally. Run prep_image first." >&2
250+
exit 1
251+
fi
252+
local runner_local="${XPK_BASE_IMAGE}__runner"
253+
sudo docker build --no-cache \
254+
--build-arg "BASEIMAGE=${XPK_BASE_IMAGE}" \
255+
--build-arg "PACKAGE_DIR=src" \
256+
-f src/dependencies/dockerfiles/maxtext_runner.Dockerfile \
257+
-t "$runner_local" .
258+
sudo docker tag "$runner_local" "$target"
259+
sudo docker push "$target"
260+
echo "Pushed: $target"
261+
}
262+
228263
# -------------------------- submit --------------------------
229264
submit_workload() {
230265
echo "Workload: $XPK_WORKLOAD"
@@ -243,6 +278,7 @@ submit_workload() {
243278
fi
244279
echo "Image flag: $image_flag=$XPK_BASE_IMAGE"
245280

281+
# PYTHONPATH covers both image flows: /deps/src (upload_runner-baked) and /app/src (xpk crane overlay).
246282
xpk workload create \
247283
--cluster "$XPK_CLUSTER" \
248284
--workload "$XPK_WORKLOAD" \
@@ -252,7 +288,7 @@ submit_workload() {
252288
--project="$XPK_PROJECT" \
253289
--zone="$XPK_ZONE" \
254290
"$image_flag=$XPK_BASE_IMAGE" \
255-
--command "export PYTHONPATH=/app/src; \
291+
--command "export PYTHONPATH=/deps/src:/app/src; \
256292
export BASE_OUTPUT_DIRECTORY=${OUTPUT_DIR}; \
257293
${gcsfuse_prelude} \
258294
python3 -m maxtext.trainers.post_train.distillation.train_distill ${XPK_DISTILL_CONFIG} \
@@ -361,6 +397,10 @@ case "$MODE" in
361397
prep_image)
362398
prep_image
363399
;;
400+
upload_runner)
401+
require_env XPK_PROJECT # GCR target; default gcloud project is usually wrong here.
402+
upload_runner
403+
;;
364404
submit|monitor|resume_until_done)
365405
require_env XPK_CLUSTER XPK_PROJECT XPK_ZONE XPK_DEVICE_TYPE XPK_BASE_OUTPUT_DIR
366406
case "$MODE" in
@@ -370,7 +410,7 @@ case "$MODE" in
370410
esac
371411
;;
372412
*)
373-
echo "Unknown mode: $MODE (use prep_image|submit|monitor|resume_until_done)" >&2
413+
echo "Unknown mode: $MODE (use prep_image|upload_runner|submit|monitor|resume_until_done)" >&2
374414
exit 1
375415
;;
376416
esac

0 commit comments

Comments
 (0)