Instructions to use KexuanShi/Megatron-LM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use KexuanShi/Megatron-LM with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
| set -exo pipefail | |
| # Increase soft limit for number of open files to match hard limit | |
| ulimit -Sn $(ulimit -Hn) | |
| # Increase soft limit for number of processes to match hard limit | |
| ulimit -Su $(ulimit -Hu) | |
| set +x | |
| for ARGUMENT in "$@"; do | |
| # Split on first = only, preserving any subsequent = signs in the value | |
| KEY="${ARGUMENT%%=*}" | |
| VALUE="${ARGUMENT#*=}" | |
| # Remove any surrounding quotes from the value if they exist | |
| VALUE="${VALUE%\"}" | |
| VALUE="${VALUE#\"}" | |
| VALUE="${VALUE%\'}" | |
| VALUE="${VALUE#\'}" | |
| # Properly quote the value to preserve spaces and special characters | |
| export "$KEY"="$(eval echo $VALUE)" | |
| echo "$KEY=$VALUE" | |
| done | |
| set -x | |
| # Check that mandatory vars are set | |
| MANDATORY_VARS=( | |
| "TRAINING_SCRIPT_PATH" | |
| "TRAINING_PARAMS_PATH" | |
| "GOLDEN_VALUES_PATH" | |
| "OUTPUT_PATH" | |
| "TENSORBOARD_PATH" | |
| "CHECKPOINT_SAVE_PATH" | |
| "CHECKPOINT_LOAD_PATH" | |
| "DATA_PATH" | |
| "DATA_CACHE_PATH" | |
| "ENABLE_LIGHTWEIGHT_MODE" | |
| ) | |
| for mandatory_var in "${MANDATORY_VARS[@]}"; do | |
| if [[ -z "${!mandatory_var}" ]]; then | |
| echo 'Providing $'$mandatory_var' is mandatory.' | |
| exit 1 | |
| fi | |
| done | |
| set -exo pipefail | |
| # Extract settings from params file | |
| TEST_TYPE=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.TEST_TYPE') | |
| ENABLE_LIGHTWEIGHT_MODE=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.ENV_VARS.ENABLE_LIGHTWEIGHT_MODE // "false"') | |
| MODE=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODE // "pretraining"') | |
| MODES=("pretraining" "inference") | |
| TEST_TYPES=("regular" "ckpt-resume" "frozen-resume" "frozen-start" "checkpoint-consistency" "release") | |
| if [[ "$TEST_TYPE" == "release" ]]; then | |
| export ONE_LOGGER_JOB_CATEGORY=production | |
| else | |
| export ONE_LOGGER_JOB_CATEGORY=test | |
| fi | |
| mkdir -p $CHECKPOINT_SAVE_PATH | |
| mkdir -p $CHECKPOINT_LOAD_PATH || true | |
| _CHECKPOINT_LOAD_PATH=$CHECKPOINT_LOAD_PATH | |
| _CHECKPOINT_SAVE_PATH=$CHECKPOINT_SAVE_PATH | |
| _TENSORBOARD_PATH=$TENSORBOARD_PATH | |
| SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) | |
| ROOT_DIR=$(realpath $SCRIPT_DIR/../../../) | |
| IS_NEMO_TEST=$([[ $(echo "$TRAINING_SCRIPT_PATH" | tr '[:upper:]' '[:lower:]') == *nemo* ]] && echo "true" || echo "false") | |
| export IS_NEMO_TEST | |
| # Adjust model_config for lightweight mode | |
| if [[ "$MODE" == "pretraining" && "$TEST_TYPE" != "release" ]]; then | |
| if [[ "$ENABLE_LIGHTWEIGHT_MODE" == "true" && "$IS_NEMO_TEST" == "true" ]]; then | |
| /usr/local/bin/yq -i '.MODEL_ARGS."trainer.max_steps" = 2' $TRAINING_PARAMS_PATH | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."trainer.max_steps // "100"') | |
| N_REPEAT=1 | |
| elif [[ "$ENABLE_LIGHTWEIGHT_MODE" == "true" && "$IS_NEMO_TEST" == "false" ]]; then | |
| /usr/local/bin/yq -i '.ENV_VARS."SKIP_PYTEST" = 1' $TRAINING_PARAMS_PATH | |
| /usr/local/bin/yq -i '.MODEL_ARGS."--exit-interval" = 4' $TRAINING_PARAMS_PATH | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."--exit-interval" // "100"') | |
| N_REPEAT=1 | |
| if [[ "$TEST_TYPE" == "ckpt-resume" || "$TEST_TYPE" == "frozen-resume" ]]; then | |
| /usr/local/bin/yq -i '.MODEL_ARGS."--save-interval" = 2' $TRAINING_PARAMS_PATH | |
| fi | |
| elif [[ "$ENABLE_LIGHTWEIGHT_MODE" == "false" && "$IS_NEMO_TEST" == "true" ]]; then | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."trainer.max_steps" // "100"') | |
| elif [[ "$ENABLE_LIGHTWEIGHT_MODE" == "false" && "$IS_NEMO_TEST" == "false" ]]; then | |
| /usr/local/bin/yq -i '.MODEL_ARGS."--exit-interval" = .MODEL_ARGS."--train-iters"' $TRAINING_PARAMS_PATH | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."--exit-interval" // "100"') | |
| fi | |
| elif [[ "$MODE" == "inference" && "$TEST_TYPE" != "release" ]]; then | |
| if [[ "$ENABLE_LIGHTWEIGHT_MODE" == "true" && "$IS_NEMO_TEST" == "false" ]]; then | |
| /usr/local/bin/yq -i '.ENV_VARS."SKIP_PYTEST" = 1' $TRAINING_PARAMS_PATH | |
| fi | |
| fi | |
| if [[ "$MODE" == "pretraining" && "$TEST_TYPE" = "release" ]]; then | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."--exit-interval" // "100"') | |
| fi | |
| # Extract settings from params file | |
| NVTE_ALLOW_NONDETERMINISTIC_ALGO=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.ENV_VARS.NVTE_ALLOW_NONDETERMINISTIC_ALGO') | |
| NON_DETERMINSTIC_RESULTS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.ENV_VARS.NON_DETERMINSTIC_RESULTS // "0"') | |
| SKIP_PYTEST=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.ENV_VARS.SKIP_PYTEST') | |
| export RECORD_CHECKPOINTS=${RECORD_CHECKPOINTS:-"false"} | |
| for i in $(seq 1 $N_REPEAT); do | |
| # Move TB logs into a repeat-specific directory | |
| DIR=$(dirname "$_TENSORBOARD_PATH") | |
| FILE=$(basename "$_TENSORBOARD_PATH") | |
| export TENSORBOARD_PATH=$DIR/$i/$FILE | |
| mkdir -p $(dirname $TENSORBOARD_PATH) | |
| if [[ $i -gt 1 ]]; then | |
| rm -rf $CHECKPOINT_SAVE_PATH/* || true | |
| rm -rf /tmp/checkpoints/* || true | |
| rm -rf $TENSORBOARD_PATH/* || true | |
| fi | |
| # First run never loads from a checkpoint | |
| export RUN_NUMBER=1 | |
| export REPEAT=$i | |
| export CHECKPOINT_SAVE_PATH=$_CHECKPOINT_SAVE_PATH | |
| export TRAINING_EXIT_CODE=0 | |
| declare -a ITER_CHECKPOINT_DIRS=() # for the grad-test check if we're doing it | |
| if [[ "$TEST_TYPE" = "frozen-start" || "$TEST_TYPE" = "checkpoint-consistency" ]]; then | |
| export CHECKPOINT_LOAD_PATH=$_CHECKPOINT_LOAD_PATH | |
| else | |
| export CHECKPOINT_LOAD_PATH=/tmp/checkpoints/ | |
| fi | |
| if [[ "$TEST_TYPE" = "release" ]]; then | |
| export CHECKPOINT_LOAD_PATH=$_CHECKPOINT_LOAD_PATH | |
| export CHECKPOINT_SAVE_PATH=$_CHECKPOINT_SAVE_PATH | |
| fi | |
| if [[ "$TEST_TYPE" = "checkpoint-consistency" ]]; then | |
| ## Loop over the list of model configs in the params file and run each one in sequence, collecting | |
| # the checkpoints. Assume that we do a single step for this test. | |
| # 1. Loop over the runs in the params file | |
| # Get all MODEL_ARGS keys from the params file | |
| mapfile -t MODEL_ARGS_KEYS < <(/usr/local/bin/yq 'keys | .[] | select(test("^MODEL_ARGS(_\\d+)?$"))' "$TRAINING_PARAMS_PATH") | |
| # For-loop over the keys | |
| for KEY in "${MODEL_ARGS_KEYS[@]}"; do | |
| [[ -z "$KEY" ]] && continue | |
| if [[ "$KEY" =~ ^MODEL_ARGS_([0-9]+)$ ]]; then | |
| export LOOP_RN="${BASH_REMATCH[1]}" | |
| elif [[ "$KEY" == "MODEL_ARGS" ]]; then | |
| export LOOP_RN=1 | |
| else | |
| echo "Unexpected KEY: $KEY" >&2; exit 1 | |
| fi | |
| export RUN_NUMBER=$LOOP_RN | |
| # Get the number of GPUs from this run. Do not export this so it clashes with the other runs. | |
| N_GPUS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ENV_VARS.'$KEY'.GPUS_PER_NODE') | |
| echo "Running $KEY with RUN_NUMBER=$RUN_NUMBER and GPUS_PER_NODE=$N_GPUS" | |
| ITER_CHECKPOINT_SAVE_PATH="$_CHECKPOINT_SAVE_PATH/repeat_${REPEAT}_key_${KEY}" | |
| mkdir -p $ITER_CHECKPOINT_SAVE_PATH | |
| # Save a checkpoint for this run | |
| GPUS_PER_NODE=$N_GPUS KEY=$KEY CHECKPOINT_SAVE_PATH=$ITER_CHECKPOINT_SAVE_PATH \ | |
| bash $ROOT_DIR/tests/functional_tests/shell_test_utils/_run_training.sh || TRAINING_EXIT_CODE=$? | |
| # TODO find out the final iter and put that at the end rather than hardcoding 1 | |
| ITER_CHECKPOINT_DIRS+=("$ITER_CHECKPOINT_SAVE_PATH/iter_0000001") | |
| done | |
| else | |
| # The standard single-run test that otherwise runs | |
| bash $ROOT_DIR/tests/functional_tests/shell_test_utils/_run_training.sh || TRAINING_EXIT_CODE=$? | |
| fi | |
| if [[ "$TEST_TYPE" = "frozen-resume" && -z "$(ls -A "$_CHECKPOINT_LOAD_PATH" 2>/dev/null)" ]]; then | |
| echo "No frozen checkpoint found. Will skip second run." | |
| export CHECKPOINT_SAVE_PATH=$_CHECKPOINT_SAVE_PATH | |
| if [[ $NODE_RANK -eq 0 ]]; then | |
| rm -rf "$CHECKPOINT_SAVE_PATH/iter_0000$TRAIN_ITERS" | |
| fi | |
| echo $((TRAIN_ITERS / 2)) >$CHECKPOINT_SAVE_PATH/latest_checkpointed_iteration.txt | |
| break | |
| fi | |
| if [[ "$TEST_TYPE" == "ckpt-resume" && "$TRAINING_EXIT_CODE" -eq 0 ]]; then | |
| export CHECKPOINT_LOAD_PATH=$CHECKPOINT_SAVE_PATH | |
| if [[ $NODE_RANK -eq 0 ]]; then | |
| rm -rf "$CHECKPOINT_LOAD_PATH/iter_$(printf "%07d\n" "$TRAIN_ITERS")" | |
| fi | |
| echo $((TRAIN_ITERS / 2)) >$CHECKPOINT_LOAD_PATH/latest_checkpointed_iteration.txt | |
| export RUN_NUMBER=2 | |
| bash $ROOT_DIR/tests/functional_tests/shell_test_utils/_run_training.sh || TRAINING_EXIT_CODE=$? | |
| fi | |
| if [[ "$TEST_TYPE" == "frozen-resume" && "$TRAINING_EXIT_CODE" -eq 0 ]]; then | |
| # Checkpoint-resume tests load from prev run | |
| export CHECKPOINT_LOAD_PATH=$_CHECKPOINT_LOAD_PATH | |
| export CHECKPOINT_SAVE_PATH=/tmp/checkpoints/ | |
| export RUN_NUMBER=2 | |
| bash $ROOT_DIR/tests/functional_tests/shell_test_utils/_run_training.sh || TRAINING_EXIT_CODE=$? | |
| export CHECKPOINT_SAVE_PATH=$_CHECKPOINT_SAVE_PATH | |
| if [[ $NODE_RANK -eq 0 ]]; then | |
| rm -rf "$CHECKPOINT_SAVE_PATH/iter_0000$TRAIN_ITERS" | |
| fi | |
| echo $((TRAIN_ITERS / 2)) >$CHECKPOINT_SAVE_PATH/latest_checkpointed_iteration.txt | |
| fi | |
| if [[ ${RECORD_CHECKPOINTS} == "true" ]]; then | |
| echo "Skipping Pytest during checkpoint recording." | |
| SKIP_PYTEST=1 | |
| fi | |
| if [[ ${SKIP_PYTEST:-0} != 1 || "$TEST_TYPE" == "release" ]]; then | |
| # Save run results | |
| export PYTHONPATH=$ROOT_DIR | |
| if [[ "$TEST_TYPE" == "release" ]]; then | |
| EXTRACT_ARGS=("--is-convergence-test") | |
| else | |
| EXTRACT_ARGS=("--is-normal-test" "--step-size" "1") | |
| fi | |
| # Read test values from Tensorboard for non-inference tests. | |
| # Inference tests will load from JSON instead. | |
| if [[ "$MODE" == "pretraining" ]]; then | |
| uv run --no-sync python $ROOT_DIR/tests/functional_tests/python_test_utils/get_test_results_from_tensorboard_logs.py \ | |
| --logs-dir $TENSORBOARD_PATH \ | |
| --train-iters $TRAIN_ITERS \ | |
| --output-path ${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH) \ | |
| "${EXTRACT_ARGS[@]}" | |
| fi | |
| fi | |
| # Maybe run tests | |
| if [[ ${SKIP_PYTEST:-0} == 1 ]]; then | |
| echo Skipping Pytest checks. | |
| exit ${TRAINING_EXIT_CODE} | |
| fi | |
| if [[ ! " ${TEST_TYPES[*]} " =~ " ${TEST_TYPE} " ]]; then | |
| echo "Test type $TEST_TYPE not yet implemented." | |
| fi | |
| if [[ ! " ${MODES[*]} " =~ " ${MODE} " ]]; then | |
| echo "Mode $MODE not yet implemented." | |
| fi | |
| export NVTE_ALLOW_NONDETERMINISTIC_ALGO | |
| if [[ "${NVTE_ALLOW_NONDETERMINISTIC_ALGO}" == "1" || "${NON_DETERMINSTIC_RESULTS}" == "1" ]]; then | |
| ALLOW_NONDETERMINISTIC_ALGO_ARG="--allow-nondeterministic-algo" | |
| fi | |
| if [[ "$SLURM_NODEID" -eq 0 ]]; then | |
| echo "Running pytest checks against golden values" | |
| # For pretraining jobs | |
| if [[ "$MODE" == "pretraining" && ("$TRAINING_EXIT_CODE" -eq 0 || "$TEST_TYPE" == "release") ]]; then | |
| if [[ "$TEST_TYPE" == "checkpoint-consistency" ]]; then | |
| echo "Running checkpoint consistency check" | |
| uv run --no-sync python $ROOT_DIR/tests/functional_tests/python_test_utils/test_optimizer_grads_match.py "${ITER_CHECKPOINT_DIRS[@]}" | |
| else | |
| uv run --no-sync pytest -s -o log_cli=true --log-cli-level=info $ROOT_DIR/tests/functional_tests/python_test_utils/test_pretraining_regular_pipeline.py \ | |
| --golden-values-path $GOLDEN_VALUES_PATH \ | |
| --actual-values-path ${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH) \ | |
| --train-iters $TRAIN_ITERS \ | |
| --model-config-path ${TRAINING_PARAMS_PATH} \ | |
| $ALLOW_NONDETERMINISTIC_ALGO_ARG | |
| if [[ "$TEST_TYPE" == "ckpt-resume" || "$TEST_TYPE" == "frozen-resume" ]]; then | |
| uv run --no-sync python $ROOT_DIR/tests/functional_tests/python_test_utils/get_test_results_from_tensorboard_logs.py \ | |
| --logs-dir $TENSORBOARD_PATH \ | |
| --train-iters $TRAIN_ITERS \ | |
| --output-path "${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH .json)_2nd.json" \ | |
| --is-second-run \ | |
| "${EXTRACT_ARGS[@]}" | |
| echo "Running pytest 1st vs 2nd run comparison" | |
| uv run --no-sync pytest -s -o log_cli=true --log-cli-level=info $ROOT_DIR/tests/functional_tests/python_test_utils/test_pretraining_resume_checkpoint_pipeline.py \ | |
| --actual-values-first-run-path ${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH) \ | |
| --actual-values-second-run-path "${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH .json)_2nd.json" \ | |
| --train-iters $TRAIN_ITERS \ | |
| --model-config-path ${TRAINING_PARAMS_PATH} \ | |
| $ALLOW_NONDETERMINISTIC_ALGO_ARG | |
| fi | |
| fi | |
| fi | |
| # For inference jobs | |
| if [[ "$MODE" == "inference" && ("$TRAINING_EXIT_CODE" -eq 0 || "$TEST_TYPE" == "release") ]]; then | |
| if [[ "$TEST_TYPE" == "frozen-start" ]]; then | |
| uv run --no-sync pytest -s -o log_cli=true --log-cli-level=info $ROOT_DIR/tests/functional_tests/python_test_utils/test_inference_regular_pipeline.py \ | |
| --golden-values-path $GOLDEN_VALUES_PATH \ | |
| --test-values-path $TENSORBOARD_PATH \ | |
| --model-config-path ${TRAINING_PARAMS_PATH} \ | |
| $ALLOW_NONDETERMINISTIC_ALGO_ARG | |
| fi | |
| fi | |
| # For rl jobs | |
| if [[ "$MODE" == "rl" && ("$TRAINING_EXIT_CODE" -eq 0 || "$TEST_TYPE" == "release") ]]; then | |
| if [[ "$TEST_TYPE" == "frozen-start" ]]; then | |
| TRAIN_ITERS=$(cat $TRAINING_PARAMS_PATH | | |
| /usr/local/bin/yq '.MODEL_ARGS."--exit-interval" // "50"') | |
| uv run --no-sync python $ROOT_DIR/tests/functional_tests/python_test_utils/get_test_results_from_tensorboard_logs.py \ | |
| --logs-dir $TENSORBOARD_PATH \ | |
| --train-iters $TRAIN_ITERS \ | |
| --output-path ${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH) \ | |
| "${EXTRACT_ARGS[@]}" | |
| uv run --no-sync pytest -s -o log_cli=true --log-cli-level=info $ROOT_DIR/tests/functional_tests/python_test_utils/test_grpo_training_loop.py \ | |
| --golden-values-path $GOLDEN_VALUES_PATH \ | |
| --test-values-path ${OUTPUT_PATH}/$(basename $GOLDEN_VALUES_PATH) \ | |
| --model-config-path ${TRAINING_PARAMS_PATH} \ | |
| $ALLOW_NONDETERMINISTIC_ALGO_ARG | |
| fi | |
| fi | |
| # Abort if training failed | |
| if [[ "$TRAINING_EXIT_CODE" -ne 0 && "$TEST_TYPE" != "release" ]]; then | |
| echo "Training failed. Aborting." | |
| exit 1 | |
| fi | |
| fi | |
| done | |