|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# This script launches a DiLoCo pre-training workload on a GKE cluster using XPK. |
| 4 | + |
| 5 | +set -e |
| 6 | + |
| 7 | +# --- Cluster Parameters --- |
| 8 | +export PROJECT_ID="${PROJECT_ID:-}" |
| 9 | +export CLUSTER_NAME="${CLUSTER_NAME:-}" |
| 10 | +export ZONE="${ZONE:-}" |
| 11 | +export RESERVATION="${RESERVATION:-}" # optional |
| 12 | +export BASE_OUTPUT_DIRECTORY="${BASE_OUTPUT_DIRECTORY:-}" # change to your own GCS bucket for logging and checkpointing |
| 13 | +export DATASET_PATH="${DATASET_PATH:-}" # change to your own GSC bucket for datasets. Make sure datasets exists |
| 14 | +export DOCKER_IMAGE="${DOCKER_IMAGE:-}" # Full path to the Docker image you pushed (e.g., gcr.io/tpu-prod-env-multipod/maxtext_jax_stable:2026-06-22) |
| 15 | +export TPU_TYPE="${TPU_TYPE:-}" # At least v5p-32 is needed to run Qwen3-30b-a3b. v5p-8 for qwen3-8b |
| 16 | +export NUM_SLICES="${NUM_SLICES:-}" # you need at least two slices to let diloco take effect |
| 17 | +export WORKLOAD_NAME="${WORKLOAD_NAME:-$(whoami)-diloco-${TPU_TYPE}-$(date +%Y%m%d-%H%M%S)}" # this will be the name of run, for logging purposes |
| 18 | + |
| 19 | +# --- Model Parameters --- |
| 20 | +export MODEL_NAME="${MODEL_NAME:-}" |
| 21 | +export PER_DEVICE_BATCH_SIZE="${PER_DEVICE_BATCH_SIZE:-8}" |
| 22 | +export MAX_TARGET_LENGTH="${MAX_TARGET_LENGTH:-2048}" |
| 23 | +export TRAINING_STEPS="${TRAINING_STEPS:-20}" |
| 24 | + |
| 25 | +# --- DiLoCo Parameters --- |
| 26 | +export DILOCO_SYNC_PERIOD="${DILOCO_SYNC_PERIOD:-10}" |
| 27 | +export DILOCO_OUTER_LR="${DILOCO_OUTER_LR:-0.1}" |
| 28 | +export DILOCO_OUTER_MOMENTUM="${DILOCO_OUTER_MOMENTUM:-0.9}" |
| 29 | + |
| 30 | +# --- XLA Flags --- |
| 31 | +export XLA_FLAGS="${XLA_FLAGS:- \ |
| 32 | + --xla_tpu_scoped_vmem_limit_kib=65536 \ |
| 33 | +--xla_tpu_bf16_emission_mode=NATIVE_EMISSION \ |
| 34 | +--xla_tpu_enable_sparse_core_reduce_scatter_v2=true \ |
| 35 | +--xla_tpu_enable_sparse_core_collective_offload_all_gather=true \ |
| 36 | +--xla_tpu_enable_sparse_core_collective_offload_2d_all_gather=true \ |
| 37 | +--xla_tpu_enable_all_gather_offload_tracing=true \ |
| 38 | +--xla_tpu_use_tc_device_shape_on_sc=True \ |
| 39 | +--xla_sc_disable_megacore_partitioning=True \ |
| 40 | +--xla_tpu_enable_async_collective_fusion_fuse_all_gather=false \ |
| 41 | +--xla_enable_async_all_gather=true \ |
| 42 | +--xla_tpu_prefer_async_allgather_to_allreduce=true \ |
| 43 | +--xla_tpu_enable_sparse_core_collective_offload_all_reduce=true \ |
| 44 | +--xla_tpu_enable_sparse_core_collective_offload_reduce_scatter=true \ |
| 45 | +--xla_tpu_enable_sparse_core_collective_offload_3d_all_gather=true \ |
| 46 | +--xla_tpu_use_single_sparse_core_for_all_gather_offload=true \ |
| 47 | +--xla_tpu_enable_concurrent_sparse_core_offloading=true \ |
| 48 | +--xla_tpu_aggressive_opt_barrier_removal=true \ |
| 49 | +--xla_tpu_enable_offloading_gather_to_sparsecore=true \ |
| 50 | +--xla_tpu_sparse_core_all_gather_latency_multiplier=1 \ |
| 51 | +--xla_tpu_sparse_core_reduce_scatter_latency_multiplier=3 \ |
| 52 | +--xla_tpu_enable_sparse_core_collective_aggregator=true \ |
| 53 | +--xla_tpu_enable_latency_hiding_layer_scheduler=true \ |
| 54 | +--xla_tpu_scheduler_percent_shared_memory_limit=150 \ |
| 55 | +--xla_tpu_enable_layer_scheduler_for_dependent_collectives=true \ |
| 56 | +--xla_tpu_enable_sparse_core_collective_offload_nd_reduce_scatter=true \ |
| 57 | +--xla_tpu_pcie_bandwidth_multiplier=0.03 \ |
| 58 | +--xla_tpu_enable_sparse_core_offload_queuing_in_lhs=true \ |
| 59 | +--xla_tpu_enable_multi_compute_overlap_in_layer_scheduler=false \ |
| 60 | + --xla_tpu_enable_3d_reduce_scatter_decomposer=false }" |
| 61 | + |
| 62 | +if [ "$NUM_SLICES" -lt 2 ]; then |
| 63 | + echo "Warning: NUM_SLICES is less than 2. DiLoCo will not take effect." |
| 64 | +fi |
| 65 | + |
| 66 | +# MaxText command |
| 67 | +MAXTEXT_COMMAND="cd /deps/src/ && \ |
| 68 | +LIBTPU_INIT_ARGS='${XLA_FLAGS}' \ |
| 69 | +python3 -m maxtext.trainers.pre_train.train \ |
| 70 | +maxtext/configs/base.yml \ |
| 71 | +run_name=$WORKLOAD_NAME \ |
| 72 | +save_config_to_gcs=true \ |
| 73 | +base_output_directory=$BASE_OUTPUT_DIRECTORY \ |
| 74 | +dataset_path=$DATASET_PATH \ |
| 75 | +dataset_name='c4/en:3.0.1' \ |
| 76 | +eval_dataset_name='c4/en:3.0.1' \ |
| 77 | +model_name=$MODEL_NAME \ |
| 78 | +tokenizer_type=huggingface \ |
| 79 | +tokenizer_path=maxtext/assets/tokenizers/qwen3-tokenizer \ |
| 80 | +per_device_batch_size=$PER_DEVICE_BATCH_SIZE \ |
| 81 | +max_target_length=$MAX_TARGET_LENGTH \ |
| 82 | +enable_diloco=true \ |
| 83 | +dcn_diloco_parallelism=$NUM_SLICES \ |
| 84 | +diloco_sync_period=$DILOCO_SYNC_PERIOD \ |
| 85 | +diloco_outer_lr=$DILOCO_OUTER_LR \ |
| 86 | +diloco_outer_momentum=$DILOCO_OUTER_MOMENTUM \ |
| 87 | +steps=$TRAINING_STEPS" |
| 88 | + |
| 89 | +# Workload Creation |
| 90 | +xpk workload create \ |
| 91 | + --cluster="$CLUSTER_NAME" \ |
| 92 | + --project="$PROJECT_ID" \ |
| 93 | + --zone="$ZONE" \ |
| 94 | + --priority=medium \ |
| 95 | + --max-restarts=0 \ |
| 96 | + --tpu-type="$TPU_TYPE" \ |
| 97 | + --num-slices="$NUM_SLICES" \ |
| 98 | + --docker-image="${DOCKER_IMAGE}" \ |
| 99 | + --workload="${WORKLOAD_NAME}" \ |
| 100 | + ${RESERVATION:+--reservation="$RESERVATION"} \ |
| 101 | + --command="${MAXTEXT_COMMAND}" |
0 commit comments