Questo tutorial mostra come addestrare un modello linguistico di grandi dimensioni (LLM) su un cluster Slurm multi-nodo e multi-GPU su Google Cloud. Il modello che utilizzi in questo tutorial si basa su un modello Qwen2 con 1,5 miliardi di parametri. Il cluster Slurm utilizza due macchine virtuali (VM) a4-highgpu-8g, ognuna delle quali dispone di 8 GPU NVIDIA B200.
Le due procedure principali descritte in questo tutorial sono le seguenti:
- Esegui il deployment di un cluster Slurm ad alte prestazioni di livello di produzione utilizzando Google Cloud Cluster Toolkit. Nell'ambito di questo deployment, crei un'immagine VM personalizzata con il software necessario preinstallato. Configura anche un'istanza di Filestore condivisa e configura il networking RDMA ad alta velocità.
- Dopo il deployment del cluster, esegui un job di pre-addestramento distribuito utilizzando il set di script che accompagnano questo tutorial. Il job utilizza la libreria Hugging Face Accelerate.
Questo tutorial è rivolto a machine learning engineer, ricercatori, amministratori e operatori di piattaforme e specialisti di dati e AI interessati al deployment di cluster Slurm ad alte prestazioni su Google Cloud per l'addestramento di LLM.
Obiettivi
- Accedi al modello Qwen2 utilizzando Hugging Face.
- Prepara l'ambiente.
- Crea ed esegui il deployment di un cluster Slurm A4 di livello di produzione.
- Addestra il modello Qwen2 utilizzando la libreria Accelerate .
- Monitorare il job.
- Eseguire la pulizia.
Costi
In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il calcolatore prezzi.
Prima di iniziare
- Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
-
Installa Google Cloud CLI.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
gcloud init -
Crea o seleziona un Google Cloud progetto.
Ruoli richiesti per selezionare o creare un progetto
- Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
-
Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto
(
roles/resourcemanager.projectCreator), che contiene l'autorizzazioneresourcemanager.projects.create. Scopri come concedere i ruoli.
-
Creare un progetto Google Cloud :
gcloud projects create PROJECT_ID
Sostituisci
PROJECT_IDcon un nome per il progetto Google Cloud che stai creando. -
Seleziona il progetto Google Cloud che hai creato:
gcloud config set project PROJECT_ID
Sostituisci
PROJECT_IDcon il nome del progetto Google Cloud .
-
Verifica che la fatturazione sia abilitata per il tuo progetto Google Cloud .
Abilita l'API richiesta:
Ruoli richiesti per abilitare le API
Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (
roles/serviceusage.serviceUsageAdmin), che include l'autorizzazioneserviceusage.services.enable. Scopri come concedere i ruoli.gcloud services enable gcloud services enable compute.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
Installa Google Cloud CLI.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
gcloud init -
Crea o seleziona un Google Cloud progetto.
Ruoli richiesti per selezionare o creare un progetto
- Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
-
Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto
(
roles/resourcemanager.projectCreator), che contiene l'autorizzazioneresourcemanager.projects.create. Scopri come concedere i ruoli.
-
Creare un progetto Google Cloud :
gcloud projects create PROJECT_ID
Sostituisci
PROJECT_IDcon un nome per il progetto Google Cloud che stai creando. -
Seleziona il progetto Google Cloud che hai creato:
gcloud config set project PROJECT_ID
Sostituisci
PROJECT_IDcon il nome del progetto Google Cloud .
-
Verifica che la fatturazione sia abilitata per il tuo progetto Google Cloud .
Abilita l'API richiesta:
Ruoli richiesti per abilitare le API
Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (
roles/serviceusage.serviceUsageAdmin), che include l'autorizzazioneserviceusage.services.enable. Scopri come concedere i ruoli.gcloud services enable gcloud services enable compute.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
Concedi ruoli al tuo account utente. Esegui il seguente comando una volta per ciascuno dei seguenti ruoli IAM:
roles/compute.admin, roles/iam.serviceAccountUser, roles/file.editor, roles/storage.admin, roles/serviceusage.serviceUsageAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Sostituisci quanto segue:
PROJECT_ID: il tuo ID progetto.USER_IDENTIFIER: l'identificatore del tuo account utente . Ad esempio:myemail@example.com.ROLE: il ruolo IAM che concedi al tuo account utente.
- Abilita il account di servizio predefinito per il tuo progetto Google Cloud :
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --project=PROJECT_ID
Sostituisci PROJECT_NUMBER con il numero del progetto. Per rivedere il numero del progetto, consulta Recuperare un progetto esistente.
- Concedi il ruolo Editor (
roles/editor) al service account predefinito:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role=roles/editor
- Crea le credenziali di autenticazione locale per il tuo account utente:
gcloud auth application-default login
- Attiva OS Login per il tuo progetto:
gcloud compute project-info add-metadata --metadata=enable-oslogin=TRUE
- Accedi o crea un account Hugging Face.
Accedere a Qwen2 utilizzando Hugging Face
Per utilizzare Hugging Face per accedere a Qwen2:
prepara l'ambiente
Per preparare l'ambiente:
Clona il repository GitHub di Cluster Toolkit:
git clone https://github.com/GoogleCloudPlatform/cluster-toolkit.gitCrea un bucket Cloud Storage:
gcloud storage buckets create gs://BUCKET_NAME \ --project=PROJECT_IDSostituisci quanto segue:
BUCKET_NAME: un nome per il bucket Cloud Storage che rispetti i requisiti di denominazione dei bucket.PROJECT_ID: l'ID del Google Cloud progetto in cui vuoi creare il bucket Cloud Storage.
Crea un cluster Slurm A4
Per creare un cluster Slurm A4:
Vai alla directory
cluster-toolkit:cd cluster-toolkitSe è la prima volta che utilizzi Cluster Toolkit, crea il file binario
gcluster:makeVai alla directory
examples/machine-learning/a4-highgpu-8g:cd examples/machine-learning/a4-highgpu-8g/Apri il file
a4high-slurm-deployment.yamle modificalo nel seguente modo:terraform_backend_defaults: type: gcs configuration: bucket: BUCKET_NAME vars: deployment_name: a4-high project_id: PROJECT_ID region: REGION zone: ZONE a4h_cluster_size: 2 a4h_reservation_name: RESERVATION_URLSostituisci quanto segue:
BUCKET_NAME: il nome del bucket Cloud Storage creato nella sezione precedente.PROJECT_ID: l'ID del progettoGoogle Cloud in cui esiste Cloud Storage e in cui vuoi creare il cluster Slurm.REGION: la regione in cui esiste la prenotazione.ZONE: la zona in cui esiste la prenotazione.RESERVATION_URL: l'URL della prenotazione che vuoi utilizzare per creare il cluster Slurm. A seconda del progetto in cui esiste la prenotazione, specifica uno dei seguenti valori:La prenotazione esiste nel tuo progetto:
RESERVATION_NAMELa prenotazione esiste in un progetto diverso e il tuo progetto può utilizzarla:
projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME
Esegui il deployment del cluster:
./gcluster deploy -d examples/machine-learning/a4-highgpu-8g/a4high-slurm-deployment.yaml examples/machine-learning/a4-highgpu-8g/a4high-slurm-blueprint.yaml --auto-approveIl comando
./gcluster deployè un processo in due fasi, che è il seguente:La prima fase crea un'immagine personalizzata con tutto il software preinstallato, il cui completamento può richiedere fino a 35 minuti.
La seconda fase esegue il deployment del cluster utilizzando l'immagine personalizzata. Questo processo dovrebbe essere completato più rapidamente rispetto alla prima fase.
Se la prima fase va a buon fine, ma la seconda no, puoi provare a eseguire nuovamente il deployment del cluster Slurm saltando la prima fase:
./gcluster deploy -d examples/machine-learning/a4-highgpu-8g/a4high-slurm-deployment.yaml examples/machine-learning/a4-highgpu-8g/a4high-slurm-blueprint.yaml --auto-approve --skip "image" -w
Prepara il workload
Per preparare il workload:
Crea script del workload
Per creare gli script che verranno utilizzati dal carico di lavoro di addestramento:
Per configurare l'ambiente virtuale Python, crea il file
install_environment.shcon i seguenti contenuti:#!/bin/bash # This script should be run ONCE on the login node to set up the # shared Python virtual environment. set -e echo "--- Creating Python virtual environment in /home ---" python3 -m venv ~/.venv echo "--- Activating virtual environment ---" source ~/.venv/bin/activate echo "--- Installing build dependencies ---" pip install --upgrade pip wheel packaging echo "--- Installing PyTorch for CUDA 12.8 ---" pip install torch --index-url https://download.pytorch.org/whl/cu128 echo "--- Installing application requirements ---" pip install -r requirements.txt echo "--- Environment setup complete. You can now submit jobs with sbatch. ---"Per specificare le configurazioni per il job di perfezionamento, crea il file
accelerate_config.yamlcon i seguenti contenuti:# Default configuration for a 2-node, 8-GPU-per-node (16 total GPUs) FSDP training job. compute_environment: "LOCAL_MACHINE" distributed_type: "FSDP" downcast_bf16: "no" machine_rank: 0 main_training_function: "main" mixed_precision: "bf16" num_machines: 2 num_processes: 16 rdzv_backend: "static" same_network: true tpu_env: [] use_cpu: falsePer specificare le attività da eseguire nei job sul cluster Slurm, crea il file
submit.slurmcon il seguente contenuto:#!/bin/bash #SBATCH --job-name=qwen2-pretrain-smollm-fineweb #SBATCH --nodes=2 #SBATCH --ntasks-per-node=8 # 8 tasks per node #SBATCH --gpus-per-task=1 # 1 GPU per task #SBATCH --partition=a4high #SBATCH --output=logs/slurm-%j.out #SBATCH --error=logs/slurm-%j.err set -e echo "--- Slurm Job Started ---" # --- STAGE 1: Setup environment and pre-process data on each node's local SSD --- # This command runs once per node. srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 bash -c ' set -e echo "Setting up local environment on $(hostname)..." LOCAL_VENV="/mnt/localssd/venv_job_${SLURM_JOB_ID}" LOCAL_CACHE="/mnt/localssd/hf_cache_job_${SLURM_JOB_ID}" PROCESSED_DATA_DIR="/mnt/localssd/processed_data_${SLURM_JOB_ID}" rsync -a --info=progress2 ~/./.venv/ ${LOCAL_VENV}/ mkdir -p ${LOCAL_CACHE} ${PROCESSED_DATA_DIR} echo "Pre-processing data on $(hostname)..." source ${LOCAL_VENV}/bin/activate export HF_HOME=${LOCAL_CACHE} export HF_DATASETS_CACHE=${LOCAL_CACHE} # This runs the new preprocessing script. It ensures only ONE process per node # downloads and processes the data, avoiding rate limiting and redundant work. python preprocess_data.py \ --dataset_name "HuggingFaceFW/fineweb-edu" \ --dataset_config "CC-MAIN-2024-10" \ --tokenizer_id "Qwen/Qwen2-1.5B" \ --max_seq_length 1024 \ --output_path ${PROCESSED_DATA_DIR} echo "Setup on $(hostname) complete." ' # --- STAGE 2: Run the Training Job using the Local Environment --- echo "--- Starting Training ---" LOCAL_VENV="/mnt/localssd/venv_job_${SLURM_JOB_ID}" PROCESSED_DATA_DIR="/mnt/localssd/processed_data_${SLURM_JOB_ID}" LOCAL_OUTPUT_DIR="/mnt/localssd/outputs_${SLURM_JOB_ID}" mkdir -p ${LOCAL_OUTPUT_DIR} # This is the main training command. It launches one Python process per GPU. srun --ntasks=$((SLURM_NNODES * 8)) --gpus-per-task=1 bash -c " source ${LOCAL_VENV}/bin/activate # The training script now loads the pre-processed data from the local SSD. python train.py \ --model_config_id "Qwen/Qwen2-1.5B" \ --preprocessed_data_path ${PROCESSED_DATA_DIR} \ --output_dir ${LOCAL_OUTPUT_DIR} \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 4 \ --max_steps 10000 \ --learning_rate 5e-5 \ --save_strategy steps \ --save_steps 500 " # --- STAGE 3: Copy Final Model from Local SSD to Home Directory --- echo "--- Copying final model from local SSD to /home ---" # This command runs only on the first node of the job allocation # and copies the final model back to the persistent shared directory. srun --nodes=1 --ntasks=1 --ntasks-per-node=1 bash -c " rsync -a --info=progress2 ${LOCAL_OUTPUT_DIR}/ ~/qwen2-from-scratch-on-smollm-fineweb/ " echo "--- Slurm Job Finished ---"Per specificare le dipendenze per il job di perfezionamento, crea un file
requirements.txtcon i seguenti contenuti:# Hugging Face Libraries (Pinned to recent, stable versions for reproducibility) transformers==4.53.3 datasets==4.0.0 accelerate==1.9.0 evaluate==0.4.5 bitsandbytes==0.46.1 trl==0.19.1 peft==0.16.0 # Other dependencies tensorboard==2.20.0 protobuf==6.31.1 sentencepiece==0.2.0Per scaricare, tokenizzare ed elaborare il set di dati in un formato pronto per l'addestramento, crea un file
preprocess_data.pycon i seguenti contenuti:import argparse from datasets import load_dataset from transformers import AutoTokenizer import os from itertools import chain def get_args(): parser = argparse.ArgumentParser(description="Download and preprocess a dataset.") parser.add_argument("--dataset_name", type=str, required=True) parser.add_argument("--dataset_config", type=str, required=True) parser.add_argument("--tokenizer_id", type=str, required=True) parser.add_argument("--max_seq_length", type=int, required=True) parser.add_argument("--output_path", type=str, required=True, help="Path to save the processed dataset.") return parser.parse_args() def main(): args = get_args() if os.path.exists(args.output_path) and os.listdir(args.output_path): print(f"Processed dataset already exists at {args.output_path}. Skipping.") return # 1. Load tokenizer tokenizer = AutoTokenizer.from_pretrained(args.tokenizer_id) # 2. Load raw dataset print(f"Loading raw dataset {args.dataset_name}...") raw_dataset = load_dataset(args.dataset_name, name=args.dataset_config, split="train") # 3. Tokenize def tokenize_function(examples): return tokenizer(examples["text"]) num_proc = os.cpu_count() print(f"Tokenizing dataset using {num_proc} processes...") print("Tokenizing dataset...") tokenized_dataset = raw_dataset.map( tokenize_function, batched=True, remove_columns=raw_dataset.column_names, desc="Running tokenizer on dataset", num_proc=num_proc, ) # 4. Group texts def group_texts(examples): concatenated_examples = {k: list(chain.from_iterable(examples[k])) for k in examples.keys()} total_length = len(concatenated_examples[list(examples.keys())[0]]) if total_length >= args.max_seq_length: total_length = (total_length // args.max_seq_length) * args.max_seq_length result = { k: [t[i : i + args.max_seq_length] for i in range(0, total_length, args.max_seq_length)] for k, t in concatenated_examples.items() } result["labels"] = result["input_ids"].copy() return result print("Grouping texts...") lm_dataset = tokenized_dataset.map( group_texts, batched=True, desc=f"Grouping texts in chunks of {args.max_seq_length}", num_proc=num_proc, ) # 5. Save to disk print(f"Saving processed dataset to {args.output_path}...") lm_dataset.save_to_disk(args.output_path) print("Preprocessing complete.") if __name__ == "__main__": main()Per specificare le istruzioni per il job, crea un file
train.pycon il seguente contenuto:import torch import argparse from datasets import load_dataset, load_from_disk import os from transformers import ( AutoConfig, AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments, DataCollatorForLanguageModeling, ) from huggingface_hub import login def get_args(): parser = argparse.ArgumentParser() parser.add_argument("--model_config_id", type=str, default="Qwen/Qwen2-1.5B", help="Hugging Face model config to use for architecture.") # Data arguments - used if preprocessed data is not available parser.add_argument("--dataset_name", type=str, default="HuggingFaceFW/fineweb-edu", help="Hugging Face dataset for pre-training.") parser.add_argument("--dataset_config", type=str, default="CC-MAIN-2024-10", help="Config for the smollm-corpus dataset, e.g., 'fineweb-edu-dedup'.") parser.add_argument("--preprocessed_data_path", type=str, default=None, help="Path to a preprocessed dataset on disk. If provided, skips download and processing.") # General arguments parser.add_argument("--hf_token", type=str, default=None, help="Hugging Face token for private models/tokenizers") parser.add_argument("--output_dir", type=str, default="qwen2-from-scratch-on-olmo", help="Directory to save model checkpoints") # TrainingArguments parser.add_argument("--max_seq_length", type=int, default=1024, help="Maximum sequence length") parser.add_argument("--num_train_epochs", type=int, default=1, help="Number of training epochs") parser.add_argument("--max_steps", type=int, default=-1, help="If set to a positive number, it overrides num_train_epochs.") parser.add_argument("--per_device_train_batch_size", type=int, default=4, help="Batch size per device during training") parser.add_argument("--gradient_accumulation_steps", type=int, default=4, help="Gradient accumulation steps") parser.add_argument("--learning_rate", type=float, default=5e-5, help="Learning rate") parser.add_argument("--logging_steps", type=int, default=10, help="Log every X steps") parser.add_argument("--save_strategy", type=str, default="steps", help="Checkpoint save strategy") parser.add_argument("--save_steps", type=int, default=500, help="Save checkpoint every X steps") return parser.parse_args() def main(): args = get_args() # --- 1. Setup and Login --- if args.hf_token: login(args.hf_token) # --- 2. Load Tokenizer --- # We load the tokenizer from the specified config ID to ensure compatibility # with the model architecture (e.g., special tokens). tokenizer = AutoTokenizer.from_pretrained(args.model_config_id) # --- 4. Initialize Model from Scratch --- print(f"Initializing a new model from {args.model_config_id} configuration...") config = AutoConfig.from_pretrained(args.model_config_id) model = AutoModelForCausalLM.from_config(config) print(f"Model has {model.num_parameters():,} parameters.") # --- 3. Load or Create and prepare the training dataset --- if args.preprocessed_data_path and os.path.exists(args.preprocessed_data_path): print(f"Loading preprocessed dataset from {args.preprocessed_data_path}...") lm_dataset = load_from_disk(args.preprocessed_data_path) else: print("No preprocessed dataset found, starting from raw data...") raw_dataset = load_dataset(args.dataset_name, name=args.dataset_config, split="train") # Tokenization function def tokenize_function(examples): return tokenizer(examples["text"]) tokenized_dataset = raw_dataset.map( tokenize_function, batched=True, remove_columns=raw_dataset.column_names, desc="Running tokenizer on dataset", ) # Main data processing function that will concatenate all texts from our dataset # and generate chunks of max_seq_length. def group_texts(examples): # Concatenate all texts. concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()} total_length = len(concatenated_examples[list(examples.keys())[0]]) # We drop the small remainder. if total_length >= args.max_seq_length: total_length = (total_length // args.max_seq_length) * args.max_seq_length # Split by chunks of max_len. result = { k: [t[i : i + args.max_seq_length] for i in range(0, total_length, args.max_seq_length)] for k, t in concatenated_examples.items() } result["labels"] = result["input_ids"].copy() return result lm_dataset = tokenized_dataset.map( group_texts, batched=True, desc=f"Grouping texts in chunks of {args.max_seq_length}", ) # --- 5. Configure Training Arguments --- # Check for bfloat16 support use_bf16 = torch.cuda.is_available() and torch.cuda.is_bf16_supported() training_args = TrainingArguments( output_dir=args.output_dir, num_train_epochs=args.num_train_epochs, max_steps=args.max_steps, per_device_train_batch_size=args.per_device_train_batch_size, gradient_accumulation_steps=args.gradient_accumulation_steps, learning_rate=args.learning_rate, logging_steps=args.logging_steps, save_strategy=args.save_strategy, save_steps=args.save_steps, save_total_limit=2, # Optional: Limit the number of checkpoints bf16=use_bf16, fp16=not use_bf16, optim="adamw_torch", lr_scheduler_type="cosine", warmup_ratio=0.03, report_to="tensorboard", gradient_checkpointing=True, # Required for gradient checkpointing with some parallelization strategies gradient_checkpointing_kwargs={"use_reentrant": False}, ) # --- 6. Create Trainer and Start Training --- # Data collator will take care of creating batches for causal language modeling data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False) trainer = Trainer( model=model, args=training_args, train_dataset=lm_dataset, # eval_dataset=... # Optional: if you have a validation set tokenizer=tokenizer, data_collator=data_collator, ) print("Starting training from scratch...") trainer.train() print("Training finished.") # --- 7. Save the final model --- print(f"Saving final model to {args.output_dir}") trainer.save_model() if __name__ == "__main__": main()
Carica gli script nel cluster Slurm
Per caricare gli script creati nella sezione precedente nel cluster Slurm, segui questi passaggi:
Per identificare il nodo di accesso, elenca tutte le VM A4 nel tuo progetto:
gcloud compute instances list --filter="machineType:a4-highgpu-8g"Il nome del nodo di accesso è simile a
a4-high-login-001.Carica gli script nella home directory del nodo di accesso:
gcloud compute scp \ --project=PROJECT_ID \ --zone=ZONE \ --tunnel-through-iap \ ./train.py \ ./requirements.txt \ ./submit.slurm \ ./install_environment.sh \ ./accelerate_config.yaml \ "LOGIN_NODE_NAME":~/Sostituisci
LOGIN_NODE_NAMEcon il nome del nodo di accesso.
Connettiti al cluster Slurm
Connettiti al cluster Slurm connettendoti al nodo di accesso tramite SSH:
gcloud compute ssh LOGIN_NODE_NAME \
--project=PROJECT_ID \
--tunnel-through-iap \
--zone=ZONE
Installare framework e strumenti
Dopo aver eseguito la connessione al nodo di accesso, installa framework e strumenti nel seguente modo:
Crea una variabile di ambiente per il token di accesso a Hugging Face:
export HUGGING_FACE_TOKEN="HUGGING_FACE_TOKEN"Configura un ambiente virtuale Python con tutte le dipendenze richieste:
chmod +x install_environment.sh ./install_environment.sh
Inizia il pre-training del tuo workload
Per iniziare l'addestramento del workload:
Invia il job allo scheduler Slurm:
sbatch submit.slurmSul nodo di accesso del cluster Slurm, puoi monitorare l'avanzamento del job controllando i file di output creati nella directory
home:tail -f logs/slurm-qwen2-pretrain-smollm-fineweb.errSe il job viene avviato correttamente, il file
.errmostra una barra dei progressi che si aggiorna man mano che il job procede.
Monitorare il workload
Puoi monitorare l'utilizzo delle GPU nel cluster Slurm per verificare che il job di ottimizzazione venga eseguito in modo efficiente. Per farlo, apri il seguente link nel browser:
https://console.cloud.google.com/monitoring/metrics-explorer?project=PROJECT_ID&pageState=%7B%22xyChart%22%3A%7B%22dataSets%22%3A%5B%7B%22timeSeriesFilter%22%3A%7B%22filter%22%3A%22metric.type%3D%5C%22agent.googleapis.com%2Fgpu%2Futilization%5C%22%20resource.type%3D%5C%22gce_instance%5C%22%22%2C%22perSeriesAligner%22%3A%22ALIGN_MEAN%22%7D%2C%22plotType%22%3A%22LINE%22%7D%5D%7D%7D
Quando monitori il carico di lavoro, puoi visualizzare quanto segue:
Utilizzo delle GPU: per un job di messa a punto ottimale, puoi aspettarti di vedere l'utilizzo di tutte le 16 GPU (8 GPU per ogni VM nel cluster) aumentare e stabilizzarsi a un livello specifico durante l'addestramento.
Durata del job: il completamento del job dovrebbe richiedere circa un'ora.
Scaricare il modello
Dopo aver eseguito correttamente il job, il modello addestrato viene salvato nella directory ~/qwen2-from-scratch-on-smollm-fineweb/ sul nodo di accesso. Poiché questa
directory condivisa permanente è montata su tutti i nodi del cluster,
i checkpoint del modello rimangono disponibili anche dopo il completamento del job o la
deallocazione dei nodi di calcolo.
Puoi scaricare il modello salvato dal nodo di accesso alla tua macchina locale
utilizzando il comando gcloud compute scp, come mostrato nell'esempio seguente:
# From your local machine
LOGIN_NODE_NAME="your-login-node-name" # e.g., a4high-login-001
PROJECT_ID="your-gcp-project-id"
ZONE="your-cluster-zone" # e.g., us-west4-a
gcloud compute scp --project="$PROJECT_ID" --zone="$ZONE" --tunnel-through-iap \
"${LOGIN_NODE_NAME}":~/qwen2-from-scratch-on-smollm-fineweb/ ./qwen2-trained-model/ --recurse
Dopo aver scaricato il modello, puoi:
- Carica il modello per l'inferenza: utilizza il framework Hugging Face Transformers
per caricare la directory
qwen2-trained-model/ed eseguire l'inferenza con il modello Qwen2 appena addestrato. - Ottimizzazione aggiuntiva: utilizza il checkpoint salvato come punto di partenza per un'ottimizzazione aggiuntiva su un set di dati più specifico.
- Trasferisci il modello a Hugging Face Hub: condividi il modello addestrato trasferendolo a Hugging Face Hub.
Esegui la pulizia
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.
Elimina il progetto
Elimina un progetto Google Cloud :
gcloud projects delete PROJECT_ID
Elimina il cluster Slurm
Per eliminare il cluster Slurm:
Vai alla directory
cluster-toolkit.Elimina il file Terraform e tutte le risorse create:
./gcluster destroy a4-high --auto-approve