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
| # This script can be used for model onboarding and testing. | |
| # For onboarding, it extract scalars from Tensorboard logs only. | |
| # For testing, it compares extracted Tensorboard scalars against | |
| # a set of `GOLDEN_VALUES`. | |
| set -euxo pipefail | |
| set +x | |
| for ARGUMENT in "$@"; do | |
| KEY=$(echo $ARGUMENT | cut -f1 -d=) | |
| KEY_LENGTH=${#KEY} | |
| VALUE="${ARGUMENT:$KEY_LENGTH+1}" | |
| export "$KEY"="$VALUE" | |
| echo "$KEY=$VALUE" | |
| done | |
| set -x | |
| # Check that mandatory vars are set | |
| MANDATORY_VARS=( | |
| "TRAINING_SCRIPT_PATH" | |
| "TRAINING_PARAMS_PATH" | |
| "OUTPUT_PATH" | |
| "TENSORBOARD_PATH" | |
| "CHECKPOINT_SAVE_PATH" | |
| "CHECKPOINT_LOAD_PATH" | |
| "DATA_PATH" | |
| "RUN_NUMBER" | |
| "REPEAT" | |
| ) | |
| for mandatory_var in "${MANDATORY_VARS[@]}"; do | |
| if [[ -z "${!mandatory_var}" ]]; then | |
| echo 'Providing $'$mandatory_var' is mandatory.' | |
| exit 1 | |
| fi | |
| done | |
| set +x | |
| # Envsubst model_params | |
| cat $TRAINING_PARAMS_PATH | envsubst "$(env | cut -d= -f1 | sed -e 's/^/$/')" >$TRAINING_PARAMS_PATH.tmp | |
| TRAINING_PARAMS_PATH="$TRAINING_PARAMS_PATH.tmp" | |
| set -x | |
| # Pull env vars to export | |
| ENV_VARS=$(/usr/local/bin/yq '... comments="" | .ENV_VARS | to_entries | .[] | [.key + "=" + .value] | join(" ")' "$TRAINING_PARAMS_PATH") | |
| while IFS= read -r ARGUMENT; do | |
| KEY=$(echo $ARGUMENT | cut -f1 -d=) | |
| KEY_LENGTH=${#KEY} | |
| VALUE="${ARGUMENT:$KEY_LENGTH+1}" | |
| export "$KEY"="$VALUE" | |
| echo "$KEY=$VALUE" | |
| done <<<"$ENV_VARS" | |
| # Run before script | |
| BEFORE_SCRIPT=$(cat "$TRAINING_PARAMS_PATH" | /usr/local/bin/yq '.BEFORE_SCRIPT') | |
| if [[ "$BEFORE_SCRIPT" != null ]]; then | |
| eval "$BEFORE_SCRIPT" | |
| fi | |
| # Exit earlier to leave time for properly saving checkpoint | |
| if [[ "$IS_NEMO_TEST" == "true" ]]; then | |
| PARAMS=() | |
| # Store the output in a variable first | |
| TRAINING_PARAMS_STR=$(/usr/local/bin/yq '... comments="" | .MODEL_ARGS | to_entries | .[] | with(select(.value == true); .value = "true") | .key + "=" + (select(.value != "") | .value | tostring)' "$TRAINING_PARAMS_PATH") | |
| # Build space-separated string while preserving quotes | |
| TRAINING_PARAMS_FROM_CONFIG="" | |
| while IFS= read -r line; do | |
| if [[ -n "$line" ]]; then | |
| # If value is "true", just use the key | |
| if [[ "$line" =~ =true$ ]]; then | |
| TRAINING_PARAMS_FROM_CONFIG+="${line%=true} " | |
| # If value contains spaces, wrap it in quotes | |
| elif [[ "$line" =~ .*=.*[[:space:]].* ]]; then | |
| key="${line%%=*}" | |
| value="${line#*=}" | |
| TRAINING_PARAMS_FROM_CONFIG+="$key=\"$value\" " | |
| else | |
| TRAINING_PARAMS_FROM_CONFIG+="$line " | |
| fi | |
| fi | |
| done <<<"$TRAINING_PARAMS_STR" | |
| # Remove trailing space | |
| TRAINING_PARAMS_FROM_CONFIG=${TRAINING_PARAMS_FROM_CONFIG% } | |
| # Split into array while preserving quotes | |
| eval "TRAINING_PARAMS_ARRAY=($TRAINING_PARAMS_FROM_CONFIG)" | |
| else | |
| # If this is a second run (of checkpoint-resume), we might want to use a | |
| # different model configuration than during first time. So if key `MODEL_ARGS_2` | |
| # exists we use it, otherwise we use the same as for the first run. | |
| if [[ $RUN_NUMBER -gt 1 && $(/usr/local/bin/yq 'has("MODEL_ARGS_'$RUN_NUMBER'")' "$TRAINING_PARAMS_PATH") == true ]]; then | |
| export KEY="MODEL_ARGS_$RUN_NUMBER" | |
| else | |
| export KEY="MODEL_ARGS" | |
| fi | |
| # Store the output in a variable first | |
| TRAINING_PARAMS_STR=$(/usr/local/bin/yq 'explode(.) | ... comments="" | .[env(KEY)] | to_entries | .[] | with(select(.value == true); .value = "true") | .key + ": " + (select(.value != "") | .value | tostring)' "$TRAINING_PARAMS_PATH") | |
| # Build space-separated string while preserving quotes | |
| TRAINING_PARAMS_FROM_CONFIG="" | |
| while IFS= read -r line; do | |
| if [[ -n "$line" ]]; then | |
| key="${line%%:*}" | |
| value="${line#*: }" | |
| value="$(echo "$value" | xargs)" # trim whitespace | |
| # Case: true | |
| if [[ "$value" == "true" ]]; then | |
| TRAINING_PARAMS_FROM_CONFIG+="${key} " | |
| # Case: value is wrapped in ( ) | |
| elif echo "$value" | grep -Eq '^\([^)]+\)$'; then | |
| TRAINING_PARAMS_FROM_CONFIG+="$key \"$value\" " | |
| # Case: value is wrapped in [ ] | |
| elif echo "$value" | grep -Eq '^\[[^]]+\]$'; then | |
| # Strip square brackets from value using sed | |
| value=$(echo "$value" | sed 's/^\[//;s/\]$//') | |
| TRAINING_PARAMS_FROM_CONFIG+="$key $value " | |
| # Case: contains spaces | |
| elif [[ "$value" == *" "* ]]; then | |
| TRAINING_PARAMS_FROM_CONFIG+="$key \"$value\" " | |
| # Case: default | |
| else | |
| TRAINING_PARAMS_FROM_CONFIG+="$key $value " | |
| fi | |
| fi | |
| done <<<"$TRAINING_PARAMS_STR" | |
| # Remove trailing space | |
| TRAINING_PARAMS_FROM_CONFIG=${TRAINING_PARAMS_FROM_CONFIG% } | |
| # Split into array while preserving quotes | |
| eval "TRAINING_PARAMS_ARRAY=($TRAINING_PARAMS_FROM_CONFIG)" | |
| if [[ -n "${SLURM_JOB_END_TIME:-}" && -n "${SLURM_JOB_START_TIME:-}" ]]; then | |
| PARAMS=( | |
| "--exit-duration-in-mins" | |
| $((($SLURM_JOB_END_TIME - $SLURM_JOB_START_TIME) / 60 - 15)) | |
| ) | |
| fi | |
| fi | |
| # Extract training params | |
| PARAMS=("${PARAMS[@]}" "${TRAINING_PARAMS_ARRAY[@]}") | |
| # Set PYTHONPATH | |
| export PYTHONPATH="$(pwd):${PYTHONPATH:-}" | |
| export WANDB_API_KEY="${WANDB_API_KEY:-}" | |
| ######## Distributed training settings. ######## | |
| echo "------ARGUMENTS for SLURM ---" | |
| MASTER_ADDR=${MASTER_ADDR:-localhost} | |
| MASTER_PORT=${MASTER_PORT:-6000} | |
| NUM_NODES=${NUM_NODES:-${SLURM_NNODES:-1}} | |
| GPUS_PER_NODE=${GPUS_PER_NODE:-8} | |
| NODE_RANK=${SLURM_NODEID:-${SLURM_NODEID:-0}} | |
| LAST_RANK=$((GPUS_PER_NODE - 1)) | |
| export LOG_DIR=$OUTPUT_PATH/logs/$REPEAT | |
| mkdir -p $LOG_DIR | |
| DISTRIBUTED_ARGS=( | |
| --nproc_per_node $GPUS_PER_NODE | |
| --nnodes $NUM_NODES | |
| --master_addr $MASTER_ADDR | |
| --master_port $MASTER_PORT | |
| --node_rank $NODE_RANK | |
| --log-dir $LOG_DIR | |
| --tee "0:3,$LAST_RANK:3" | |
| --redirects "3" | |
| ) | |
| # Start training | |
| if [[ "$IS_NEMO_TEST" == "true" ]]; then | |
| uv run --no-sync python -m torch.distributed.run ${DISTRIBUTED_ARGS[@]} \ | |
| --no-python /opt/venv/bin/$TRAINING_SCRIPT_PATH "${PARAMS[@]}" && EXIT_CODE=0 || EXIT_CODE=$? | |
| else | |
| uv run --no-sync python -m torch.distributed.run ${DISTRIBUTED_ARGS[@]} \ | |
| $TRAINING_SCRIPT_PATH "${PARAMS[@]}" && EXIT_CODE=0 || EXIT_CODE=$? | |
| fi | |
| # Run after script | |
| AFTER_SCRIPT=$(cat "$TRAINING_PARAMS_PATH" | /usr/local/bin/yq '.AFTER_SCRIPT') | |
| if [[ "$AFTER_SCRIPT" != null ]]; then | |
| eval "$AFTER_SCRIPT" | |
| fi | |
| # Set permissions | |
| chmod -R g+w $OUTPUT_PATH | |
| if [[ ${RECORD_CHECKPOINTS} == "true" ]]; then | |
| echo "Suppressing errors during checkpoint recording." | |
| exit 0 | |
| fi | |
| exit ${EXIT_CODE:-0} | |