이 튜토리얼에서는 Google Cloud에서 멀티 노드, 멀티 GPU Slurm 클러스터에서 Llama-4-Scout-17 대규모 언어 모델 (LLM)을 미세 조정하는 방법을 보여줍니다. 클러스터는 각각 8개의 NVIDIA B200 GPU가 있는 두 개의 A4 가상 머신 (VM) 인스턴스를 사용합니다.
이 튜토리얼에 설명된 두 가지 주요 프로세스는 다음과 같습니다.
- Google Cloud Cluster Toolkit을 사용하여 프로덕션급 고성능 Slurm 클러스터를 배포합니다. 이 배포의 일환으로 필요한 소프트웨어가 사전 설치된 맞춤 VM 이미지를 만듭니다. 공유 Filestore 인스턴스를 설정하고 고속 RDMA 네트워킹을 구성합니다.
- 클러스터가 배포되면 이 튜토리얼에 포함된 스크립트 집합을 사용하여 분산 미세 조정 작업을 실행합니다. 이 작업은 PyTorch 완전 샤딩된 데이터 동시 로드 (FSDP)를 활용하며, 이는 Hugging Face Transformer 강화 학습
이 튜토리얼은 Slurm 작업 예약 기능을 사용하여 미세 조정 워크로드를 처리하는 데 관심이 있는 머신러닝 (ML) 엔지니어, 플랫폼 관리자 및 운영자, 데이터 및 AI 전문가를 대상으로 합니다.
목표
Hugging Face를 사용하여 Llama 4에 액세스
개발 환경 준비
프로덕션 등급 A4 High-GPU Slurm 클러스터를 만들고 배포합니다.
FSDP를 사용한 분산 학습을 위해 다중 노드 환경을 구성합니다.
Hugging Face
trl.SFTTrainer를 사용하여 Llama 4 모델을 파인 튜닝합니다.로컬 SSD에 데이터를 스테이징합니다.
작업 모니터링
삭제
비용
이 문서에서는 비용이 청구될 수 있는 Google Cloud구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
시작하기 전에
- Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
Google Cloud 프로젝트를 만들거나 선택합니다.
프로젝트를 선택하거나 만드는 데 필요한 역할
- 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
Google Cloud 프로젝트를 만듭니다.
gcloud projects create PROJECT_ID
PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다. -
생성한 Google Cloud 프로젝트를 선택합니다.
gcloud config set project PROJECT_ID
PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.
필요한 API를 사용 설정합니다.
API 사용 설정에 필요한 역할
API를 사용 설정하려면
serviceusage.services.enable권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기gcloud services enable compute.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
Google Cloud CLI를 설치합니다.
-
외부 ID 공급업체(IdP)를 사용하는 경우 먼저 제휴 ID로 gcloud CLI에 로그인해야 합니다.
-
gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.
gcloud init -
Google Cloud 프로젝트를 만들거나 선택합니다.
프로젝트를 선택하거나 만드는 데 필요한 역할
- 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
-
프로젝트 만들기: 프로젝트를 만들려면
resourcemanager.projects.create권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
-
Google Cloud 프로젝트를 만듭니다.
gcloud projects create PROJECT_ID
PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다. -
생성한 Google Cloud 프로젝트를 선택합니다.
gcloud config set project PROJECT_ID
PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.
필요한 API를 사용 설정합니다.
API 사용 설정에 필요한 역할
API를 사용 설정하려면
serviceusage.services.enable권한이 포함된 서비스 사용량 관리자 IAM 역할 (roles/serviceusage.serviceUsageAdmin)이 필요합니다. 역할 부여 방법 알아보기gcloud services enable compute.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
사용자 계정에 역할을 부여합니다. 다음 IAM 역할마다 다음 명령어를 1회 실행합니다.
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
다음을 바꿉니다.
PROJECT_ID: 프로젝트 ID입니다.USER_IDENTIFIER: 사용자 계정의 식별자입니다. 예를 들면myemail@example.com입니다.ROLE: 사용자 계정에 부여하는 IAM 역할입니다.
- Google Cloud 프로젝트의 기본 서비스 계정을 사용 설정합니다.
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com
--project=PROJECT_ID여기에서 PROJECT_NUMBER를 프로젝트 번호로 바꿉니다. 프로젝트 번호를 검토하려면 기존 프로젝트 가져오기를 참고하세요.
- 기본 서비스 계정에 편집자 역할 (
roles/editor)을 부여합니다.gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com"
--role=roles/editor - 사용자 계정의 로컬 인증 사용자 인증 정보를 만듭니다.
gcloud auth application-default login
- 프로젝트에 OS 로그인을 사용 설정합니다.
gcloud compute project-info add-metadata --metadata=enable-oslogin=TRUE
- Hugging Face 계정에 로그인하거나 계정을 만듭니다.
- 클러스터 툴킷을 사용하는 데 필요한 종속 항목을 설치합니다.
Hugging Face를 사용하여 Llama 4에 액세스
Hugging Face를 사용하여 Llama 4에 액세스하려면 다음 단계를 따르세요.
Hugging Face
read액세스 토큰을 만듭니다.내 프로필 > 설정 > 액세스 토큰 > +새 토큰 만들기를 클릭합니다.
read access토큰 값을 복사하여 저장합니다. 이 값은 이 튜토리얼의 뒷부분에서 사용합니다.
개발 환경 준비
환경을 준비하려면 다음 단계를 수행합니다.
Cluster Toolkit GitHub 저장소를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/cluster-toolkit.gitCloud Storage 버킷을 만듭니다.
gcloud storage buckets create gs://BUCKET_NAME \ --project=PROJECT_ID다음을 바꿉니다.
BUCKET_NAME: 버킷 이름 지정 요구사항을 따르는 Cloud Storage 버킷의 이름.PROJECT_ID: Cloud Storage 버킷을 만들Google Cloud 프로젝트의 ID입니다.
A4 Slurm 클러스터 만들기
A4 Slurm 클러스터를 만들려면 다음 단계를 따르세요.
cluster-toolkit디렉터리로 이동합니다.cd cluster-toolkitCluster Toolkit을 처음 사용하는 경우
gcluster바이너리를 빌드합니다.makeexamples/machine-learning/a4-highgpu-8g디렉터리로 이동합니다.cd examples/machine-learning/a4-highgpu-8g/a4high-slurm-deployment.yaml파일을 열고 다음과 같이 수정합니다.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_URL다음을 바꿉니다.
BUCKET_NAME: 이전 섹션에서 만든 Cloud Storage 버킷의 이름입니다.PROJECT_ID: Cloud Storage가 있고 Slurm 클러스터를 만들려는Google Cloud 프로젝트의 ID입니다.REGION: 예약이 있는 리전입니다.ZONE: 예약이 있는 영역입니다.RESERVATION_URL: Slurm 클러스터를 만드는 데 사용할 예약의 URL입니다. 예약이 있는 프로젝트에 따라 다음 값 중 하나를 지정합니다.예약이 프로젝트에 있는 경우:
RESERVATION_NAME예약이 다른 프로젝트에 있고 내 프로젝트에서 예약을 사용할 수 있는 경우:
projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME
클러스터를 배포합니다.
./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./gcluster deploy명령어는 다음과 같은 2단계 프로세스입니다.첫 번째 단계에서는 모든 소프트웨어가 사전 설치된 맞춤 이미지를 빌드하며, 완료하는 데 최대 35분이 걸릴 수 있습니다.
두 번째 단계에서는 해당 맞춤 이미지를 사용하여 클러스터를 배포합니다. 이 프로세스는 첫 번째 단계보다 더 빨리 완료됩니다.
첫 번째 단계는 성공했지만 두 번째 단계가 실패한 경우 첫 번째 단계를 건너뛰고 Slurm 클러스터를 다시 배포해 볼 수 있습니다.
./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
워크로드 준비
워크로드를 준비하려면 다음을 실행하세요.
워크로드 스크립트 만들기
미세 조정 워크로드에서 사용할 스크립트를 만들려면 다음 단계를 따르세요.
Python 가상 환경을 설정하려면 다음 콘텐츠가 포함된
install_environment.sh파일을 만듭니다.#!/bin/bash # This script sets up a consistent environment for FSDP training. # It is meant to be run once on the login node of your Slurm cluster set -e # --- 1. Create the Python virtual environment --- VENV_PATH="$HOME/.venv/venv-fsdp" if [ ! -d "$VENV_PATH" ]; then echo "--- Creating Python virtual environment at $VENV_PATH ---" python3 -m venv $VENV_PATH else echo "--- Virtual environment already exists at $VENV_PATH ---" fi source $VENV_PATH/bin/activate # --- 2. Install Dependencies --- echo "--- [STEP 2.1] Upgrading build toolchain ---" pip install --upgrade pip wheel packaging echo "--- [STEP 2.2] Installing PyTorch Nightly ---" pip install --force-reinstall --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128 echo "--- [STEP 2.3] Installing application dependencies ---" if [ -f "requirements-fsdp.txt" ]; then pip install -r requirements-fsdp.txt else echo "ERROR: requirements-fsdp.txt not found!" exit 1 fi # --- 3. Download the Model --- echo "--- [STEP 2.4] Downloading Llama4 model ---" if [ -z "$HF_TOKEN" ]; then echo "ERROR: The HF_TOKEN environment variable is not set."; exit 1; fi pip install huggingface_hub[cli] # Execute the CLI using its full, explicit path $VENV_PATH/bin/huggingface-cli download meta-llama/Llama-4-Scout-17B-16E-Instruct --local-dir ~/Llama-4-Scout-17B-16E-Instruct --token $HF_TOKEN echo "--- Environment setup complete. ---"이 스크립트는 안정적인 Python 가상 환경을 설정하고, PyTorch 야간 빌드를 설치하고, Llama 4 모델을 다운로드합니다.
학습 스크립트의 Python 종속 항목을 지정하려면 다음 콘텐츠로
requirements-fsdp.txt파일을 만듭니다.transformers==4.55.0 datasets==4.0.0 peft==0.16.0 accelerate==1.9.0 trl==0.21.0 # Other dependencies sentencepiece==0.2.0llama4-train-distributed.py를 기본 학습 스크립트로 지정합니다.import torch from datasets import load_dataset from peft import LoraConfig, PeftModel from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, HfArgumentParser, ) from torch.distributed import get_rank, get_world_size from transformers.models.llama4.modeling_llama4 import Llama4TextDecoderLayer from trl import SFTTrainer from dataclasses import dataclass, field from typing import Optional @dataclass class ScriptArguments: model_id: str = field(metadata={"help": "Hugging Face model ID from the Hub"}) dataset_name: str = field(default="philschmid/gretel-synthetic-text-to-sql", metadata={"help": "Dataset from the Hub"}) run_inference_after_training: bool = field(default=False, metadata={"help": "Run sample inference on rank 0 after training"}) dataset_subset_size: Optional[int] = field(default=None, metadata={"help": "Number of samples to use from the dataset for training. If None, uses the full dataset."}) @dataclass class PeftArguments: lora_r: int = field(default=16, metadata={"help": "LoRA attention dimension"}) lora_alpha: int = field(default=32, metadata={"help": "LoRA alpha scaling factor"}) lora_dropout: float = field(default=0.05, metadata={"help": "LoRA dropout probability"}) @dataclass class SftTrainingArguments(TrainingArguments): max_length: Optional[int] = field(default=2048, metadata={"help": "The maximum sequence length for SFTTrainer"}) packing: Optional[bool] = field(default=False, metadata={"help": "Enable packing for SFTTrainer"}) ddp_find_unused_parameters: Optional[bool] = field(default=True, metadata={"help": "When using FSDP activation checkpointing, this must be set to True"}) def formatting_prompts_func(example): system_message = "You are a text to SQL query translator. Users will ask you questions in English and you will generate a SQL query based on the provided SCHEMA." user_prompt = f"### SCHEMA:\n{example['sql_context']}\n\n### USER QUERY:\n{example['sql_prompt']}" response = f"\n\n### SQL QUERY:\n{example['sql']}" return f"{system_message}\n\n{user_prompt}{response}" def main(): parser = HfArgumentParser((ScriptArguments, PeftArguments, SftTrainingArguments)) script_args, peft_args, training_args = parser.parse_args_into_dataclasses() training_args.gradient_checkpointing = True training_args.gradient_checkpointing_kwargs = {"use_reentrant": False} training_args.optim = "adamw_torch_fused" training_args.fsdp = "full_shard" training_args.fsdp_config = { "fsdp_auto_wrap_policy": "TRANSFORMER_BASED_WRAP", "fsdp_transformer_layer_cls_to_wrap": [Llama4TextDecoderLayer], "fsdp_state_dict_type": "FULL_STATE_DICT", "fsdp_offload_params": False, "fsdp_forward_prefetch": True, } tokenizer = AutoTokenizer.from_pretrained(script_args.model_id, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( script_args.model_id, torch_dtype=torch.bfloat16, trust_remote_code=True, attn_implementation="sdpa", ) peft_config = LoraConfig( r=peft_args.lora_r, lora_alpha=peft_args.lora_alpha, lora_dropout=peft_args.lora_dropout, bias="none", task_type="CAUSAL_LM", target_modules=["q_proj", "v_proj", "k_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], ) rank = get_rank() world_size = get_world_size() dataset = load_dataset(script_args.dataset_name, split="train") if script_args.dataset_subset_size is not None: dataset = dataset.select(range(script_args.dataset_subset_size)) else: print(f"Using the full dataset with {len(dataset)} samples.") dataset = dataset.shuffle(seed=training_args.seed) print(f"Dataset shuffled with seed: {training_args.seed}.") if world_size > 1: print(f"Sharding dataset for Rank {rank} of {world_size}.") dataset = dataset.shard(num_shards=world_size, index=rank) print("Initializing SFTTrainer...") trainer = SFTTrainer( model=model, args=training_args, train_dataset=dataset, peft_config=peft_config, formatting_func=formatting_prompts_func, processing_class=tokenizer, ) trainer.train() trainer.save_model(training_args.output_dir) if script_args.run_inference_after_training and trainer.is_world_process_zero(): del model del trainer torch.cuda.empty_cache() run_post_training_inference(script_args, training_args, tokenizer) def run_post_training_inference(script_args, training_args, tokenizer): """ Loads the fine-tuned PEFT adapter from the local output directory and runs inference. This should only be called on rank 0 after training is complete. """ print("\n" + "="*50) print("=== RUNNING POST-TRAINING INFERENCE TEST ===") print("="*50 + "\n") # Load the base model and merge the adapter. base_model = AutoModelForCausalLM.from_pretrained( script_args.model_id, torch_dtype=torch.bfloat16, trust_remote_code=True, device_map="auto" ) # Load the PEFT adapter and merge it into the base model model = PeftModel.from_pretrained(base_model, training_args.output_dir) model = model.merge_and_unload() # Merge weights for faster inference model.eval() # Define the test case schema = "CREATE TABLE artists (Name TEXT, Country TEXT, Genre TEXT)" system_message = "You are a text to SQL query translator. Users will ask you questions in English and you will generate a SQL query based on the provided SCHEMA." question = "Show me all artists from the Country just north of the USA." # This must match the formatting_func exactly prompt = f"{system_message}\n\n### SCHEMA:\n{schema}\n\n### USER QUERY:\n{question}\n\n### SQL QUERY:\n" print(f"Test Prompt:\n{prompt}") inputs = tokenizer(prompt, return_tensors="pt").to("cuda") print("\n--- Generating SQL... ---") outputs = model.generate( **inputs, max_new_tokens=100, pad_token_id=tokenizer.eos_token_id, do_sample=False, temperature=None, top_p=None, ) generated_sql = tokenizer.decode(outputs[0], skip_special_tokens=True)[len(prompt):].strip() print(f"\n--- Generated SQL Query ---") print(generated_sql) print("\n" + "="*50) print("=== INFERENCE TEST COMPLETE ===") print("="*50 + "\n") if __name__ == "__main__": main()이 스크립트는 TRL 감독 학습 (SFT) 트레이너를 활용하여 FSDP 학습 루프, LoRA (Low-Rank Adaptation) 구성, 데이터 형식을 관리합니다.
Slurm 클러스터에서 실행할 작업의 작업을 지정하려면 다음 콘텐츠가 포함된
submit.slurm파일을 만듭니다.#!/bin/bash #SBATCH --job-name=llama4-fsdp-fixed #SBATCH --nodes=2 #SBATCH --ntasks-per-node=8 #SBATCH --gpus-per-node=8 #SBATCH --partition=a4high #SBATCH --output=llama4-%j.out #SBATCH --error=llama4-%j.err set -e set -x echo "--- Slurm Job Started ---" echo "Job ID: $SLURM_JOB_ID" echo "Node List: $SLURM_JOB_NODELIST" # --- Define Paths --- LOCAL_SSD_PATH="/mnt/localssd/job_${SLURM_JOB_ID}" VENV_PATH="${HOME}/.venv/venv-fsdp" MODEL_PATH="${HOME}/Llama-4-Scout-17B-16E-Instruct" # --- STAGE 1: Stage Data to Local SSD on Each Node --- srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 bash -c " echo '--- Staging on node: $(hostname) ---' mkdir -p ${LOCAL_SSD_PATH} echo 'Copying virtual environment...' rsync -a -q ${VENV_PATH}/ ${LOCAL_SSD_PATH}/venv/ echo 'Copying model weights...' rsync -a --info=progress2 ${MODEL_PATH}/ ${LOCAL_SSD_PATH}/model/ mkdir -p ${LOCAL_SSD_PATH}/hf_cache echo '--- Staging on $(hostname) complete ---' " echo "--- Staging complete on all nodes ---" # --- STAGE 2: Run the Training Job --- echo "--- Launching Distributed Training with GIB NCCL Plugin ---" nodes=( $( scontrol show hostnames "$SLURM_JOB_NODELIST" ) ) head_node=${nodes[0]} head_node_ip=$(srun --nodes=1 --ntasks=1 -w "$head_node" hostname --ip-address) export MASTER_ADDR=$head_node_ip export MASTER_PORT=29500 export NCCL_SOCKET_IFNAME=enp0s19 export NCCL_NET=gIB # export NCCL_DEBUG=INFO # Un-comment to diagnose NCCL issues if needed srun --cpu-bind=none --accel-bind=g bash -c ' # Activate the environment from the local copy source '${LOCAL_SSD_PATH}'/venv/bin/activate # Point Hugging Face cache to the local SSD export HF_HOME='${LOCAL_SSD_PATH}'/hf_cache export RANK=$SLURM_PROCID export WORLD_SIZE=$SLURM_NTASKS export LOCAL_RANK=$SLURM_LOCALID export LD_LIBRARY_PATH=/usr/local/gib/lib64:$LD_LIBRARY_PATH source /usr/local/gib/scripts/set_nccl_env.sh # --- Launch the training --- python \ '${SLURM_SUBMIT_DIR}'/llama4-train-distributed.py \ --model_id="'${LOCAL_SSD_PATH}'/model/" \ --output_dir="'${LOCAL_SSD_PATH}'/outputs/" \ --dataset_name="philschmid/gretel-synthetic-text-to-sql" \ --seed=900913 \ --bf16=True \ --num_train_epochs=1 \ --per_device_train_batch_size=2 \ --gradient_accumulation_steps=4 \ --learning_rate=2e-5 \ --logging_steps=10 \ --lora_r=16 \ --lora_alpha=32 \ --lora_dropout=0.05 \ --run_inference_after_training ' # --- STAGE 3: Copy Final Results Back to Persistent Storage --- echo "--- Copying final results from local SSD to shared storage ---" PERSISTENT_OUTPUT_DIR="${HOME}/outputs/llama4_job_${SLURM_JOB_ID}" mkdir -p "$PERSISTENT_OUTPUT_DIR" # Only copy from the head node where trl has combined the results srun --nodes=1 --ntasks=1 -w "$head_node" \ rsync -a --info=progress2 "${LOCAL_SSD_PATH}/outputs/" "${PERSISTENT_OUTPUT_DIR}/" # --- STAGE 4: Cleanup --- echo "--- Cleaning up local SSD on all nodes ---" srun --ntasks=$SLURM_NNODES --ntasks-per-node=1 bash -c "rm -rf ${LOCAL_SSD_PATH}" echo "--- Slurm Job Finished ---"
Slurm 클러스터에 스크립트 업로드
이전 섹션에서 만든 스크립트를 Slurm 클러스터에 업로드하려면 다음 단계를 따르세요.
로그인 노드를 식별하려면 프로젝트의 모든 A4 VM을 나열합니다.
gcloud compute instances list --filter="machineType:a4-highgpu-8g"로그인 노드의 이름은
a4-high-login-001와 유사합니다.로그인 노드의 홈 디렉터리에 스크립트를 업로드합니다.
gcloud compute scp --project="$PROJECT_ID" --zone="$ZONE" --tunnel-through-iap \ ./install_environment.sh \ ./requirements-fsdp.txt \ ./llama4-train-distributed.py \ ./submit.slurm \ "${LOGIN_NODE_NAME}":~/LOGIN_NODE_NAME을 로그인 노드의 이름으로 바꿉니다.
Slurm 클러스터에 연결
SSH를 통해 로그인 노드에 연결하여 Slurm 클러스터에 연결합니다.
gcloud compute ssh LOGIN_NODE_NAME \
--project=PROJECT_ID \
--tunnel-through-iap \
--zone=ZONE
프레임워크 및 도구 설치
로그인 노드에 연결한 후 다음을 실행하여 프레임워크와 도구를 설치합니다.
Hugging Face 토큰을 내보냅니다.
# On the login node export HF_TOKEN="hf_..." # Replace with your token설치 스크립트를 실행합니다.
# On the login node chmod +x install_environment.sh ./install_environment.sh이 명령어는 필요한 모든 종속 항목이 포함된 가상 환경을 설정하고 모델 가중치를
~/Llama-4-Scout-17B-16E-Instruct파일에 다운로드합니다.모델 다운로드 크기가 매우 크기 때문에 (~200GB) 네트워크 상태에 따라 이 프로세스에 약 30분이 걸립니다.
미세 조정 워크로드 시작
워크로드 학습을 시작하려면 다음 단계를 따르세요.
Slurm 스케줄러에 작업을 제출합니다.
sbatch submit.slurmSlurm 클러스터의 로그인 노드에서
home디렉터리에 생성된 출력 파일을 확인하여 작업의 진행 상황을 모니터링할 수 있습니다.# On the login node tail -f llama4-*.out작업이 성공적으로 시작되면
.err파일에 작업이 진행됨에 따라 업데이트되는 진행률 표시줄이 표시됩니다.이 작업은 Slurm 클러스터에서 완료하는 데 1시간이 조금 넘게 걸립니다. 작업에는 두 가지 주요 단계가 있습니다.
- 각 컴퓨팅 노드의 로컬 SSD에 대규모 기본 모델을 복사합니다.
- 모델 복사가 완료되면 시작되는 학습 작업입니다. 이 작업을 실행하는 데 약 35분이 소요됩니다.
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
프로젝트 삭제
Google Cloud 프로젝트를 삭제합니다.
gcloud projects delete PROJECT_ID
Slurm 클러스터 삭제
Slurm 클러스터를 삭제하려면 다음 단계를 따르세요.
cluster-toolkit디렉터리로 이동합니다.Terraform 파일과 생성된 모든 리소스를 폐기합니다.
./gcluster destroy a4-high --auto-approve
Filestore 인스턴스 삭제
기본적으로 Filestore 인스턴스의 cluster-toolkit 청사진에서 deletion_protection 설정이 true로 설정되어 있습니다. 이 설정은 환경을 수정할 때 실수로 인한 데이터 손실을 방지합니다. Filestore 인스턴스를 삭제하려면 삭제 보호를 수동으로 사용 중지해야 합니다.