已合并
add llm script glm4 and llama3s #37370
HandsoemLemon创建于 6月1日
add llm script glm4 and llama3s #37370
已合并
HandsoemLemon创建于 6月1日
6 个文件变更+1078-0
Abenchmarks/llm/glm4-9B-chat/README.md+106-0
@@ -0,0 +1,106 @@
1+# glm4-9B-chat 微调训练
2+ 
3+本 README 说明如何使用 **glm4-9B-chat** 模型权重,结合 **LlamaFactory** 提供的 `c4_demo.jsonl` 示例数据,完成数据下载、预处理与训练启动(含 eager / torch.compile 两种模式)。
4+ 
5+---
6+ 
7+## 目录
8+ 
9+- [1. 模型权重](#1-模型权重)
10+- [2. 数据获取](#2-数据获取)
11+- [3. 数据预处理](#3-数据预处理)
12+- [4. 模型训练](#4-模型训练)
13+ - [4.1 eager mode(默认)](#41-eager-mode默认)
14+ - [4.2 启用 torchcompile(可选)](#42-启用-torchcompile可选)
15+ - [4.3 采集profile文件(可选)](#43-采集profile文件可选)
16+ 
17+---
18+ 
19+## 1. 模型权重
20+ 
21+- Hugging Face 模型:**glm4-9B-chat**
22+ https://huggingface.co/zai-org/glm-4-9b-chat
23+ 
24+可在链接页面中 `Files and versions` 一栏直接下载。
25+ 
26+### 环境提示
27+ 
28+本项目依赖已整理到 `requirements.txt`,可直接安装:
29+ 
30+```bash
31+pip install -r ../utils/requirements.txt
32+```
33+ 
34+## 2. 数据获取
35+ 
36+训练数据集来自 LlamaFactory 仓库示例数据,可直接在如下连接获取:
37+ 
38+- `c4_demo.json`
39+ https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
40+ 
41+或直接下载 raw 文件到本地::
42+ 
43+```bash
44+wget -O c4_demo.json \
45+https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
46+```
47+ 
48+## 3. 数据预处理
49+ 
50+`train_glm4_9B.py`中已经对数据进行了处理
51+ 
52+## 4. 模型训练
53+ 
54+训练脚本:`train_glm4_9B.sh`,脚本支持在 GPU 和 NPU 训练
55+ 
56+开始训练前,请修改脚本中的路径参数:
57+ 
58+- 模型权重路径(本地目录)
59+- 训练数据路径(预处理后的 `train.json`
60+ 
61+### 4.1 eager mode(默认)
62+ 
63+```bash
64+bash train_glm4_9B.sh
65+```
66+ 
67+### 4.2 启用 `torch.compile`(可选)
68+ 
69+可通过添加 `--enable_compile` 选项运行图模式
70+当在 GPU 上训练时,默认后端使用triton;当在 NPU 上训练时,可进一步指定后端为 mlir 或 dvm,默认使用 mlir。
71+ 
72+**默认后端(mlir,可不写 --npu-backend):**
73+ 
74+```bash
75+bash train_glm4_9B.sh \
76+ --enable_compile
77+```
78+ 
79+**显式指定后端为 mlir:**
80+ 
81+```bash
82+bash train_glm4_9B.sh \
83+ --enable_compile \
84+ --npu-backend mlir
85+```
86+ 
87+**切换后端为 dvm::**
88+ 
89+```bash
90+bash train_glm4_9B.sh \
91+ --enable_compile \
92+ --npu-backend dvm
93+```
94+ 
95+### 4.3 采集profile文件(可选)
96+ 
97+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
98+ 
99+```bash
100+bash train_glm4_9B.sh \
101+ --enable_profiler \
102+ --profiler_start_step 5 \
103+ --profiler_end_step 6 \
104+```
105+ 
106+可以通过 `--profiler_start_step``--profiler_end_step` 分别设置profile开始和结束步数。结束步数。
Abenchmarks/llm/glm4-9B-chat/run_glm4_9B.sh+20-0
@@ -0,0 +1,20 @@
1+export TORCHINDUCTOR_CACHE_DIR='./cache'
2+export ASCEND_RT_VISIBLE_DEVICES=0
3+export TORCH_COMPILE_DEBUG=1
4+export TORCH_NPU_USE_COMPATIBLE_IMPL=1
5+ 
6+rm -rf ./cache/*
7+mkdir -p ./cache logs
8+ 
9+python train_glm4_9B.py \
10+ --model_path "your model path" \
11+ --data_path "dataset path" \
12+ --output_dir "./glm4-finetuned" \
13+ --num_epochs 3 \
14+ --max_steps 200 \
15+ --batch_size 1 \
16+ --learning_rate 2e-5 \
17+ --max_length 512 \
18+ --use_lora \
19+ --use_bf16 \
20+ --pad_to_max_length > logs/train_glm4.log 2>&1
Abenchmarks/llm/glm4-9B-chat/train_glm4_9B.py+424-0
@@ -0,0 +1,424 @@
1+import torch
2+import os
3+import sys
4+from pathlib import Path
5+import torch.nn as nn
6+from datasets import Dataset, load_dataset
7+from transformers import (
8+ AutoModelForCausalLM,
9+ AutoTokenizer,
10+ TrainingArguments,
11+ Trainer,
12+ DataCollatorForLanguageModeling,
13+ BitsAndBytesConfig,
14+)
15+from peft import (
16+ LoraConfig,
17+ get_peft_model,
18+ prepare_model_for_kbit_training,
19+ TaskType
20+)
21+import json
22+from typing import Dict, Union, Any, Optional
23+import argparse
24+import logging
25+ 
26+ 
27+sys.path.append(str(Path(__file__).parent.parent))
28+from utils.utils import (
29+ TimingCallback,
30+ get_profile,
31+ detect_device_type
32+)
33+ 
34+logging.basicConfig(level=logging.INFO)
35+logger = logging.getLogger(__name__)
36+ 
37+model_name = 'GLM4-9B'
38+ 
39+class CustomTrainer(Trainer):
40+ def compute_loss(
41+ self,
42+ model: nn.Module,
43+ inputs: Dict[str, Union[torch.Tensor, Any]],
44+ return_outputs: bool = False,
45+ num_items_in_batch: Optional[torch.Tensor] = None,
46+ ):
47+ return super().compute_loss(
48+ model=model,
49+ inputs=inputs,
50+ return_outputs=return_outputs,
51+ num_items_in_batch=None
52+ )
53+ 
54+class GLM4Trainer:
55+ def __init__(self, args):
56+ self.args = args
57+ self.setup_training()
58+ 
59+ def setup_training(self):
60+ logger.info(f"Loading GLM-4 model from {self.args.model_path}")
61+ 
62+ bnb_config = None
63+ if self.args.use_4bit:
64+ bnb_config = BitsAndBytesConfig(
65+ load_in_4bit=True,
66+ bnb_4bit_quant_type="nf4",
67+ bnb_4bit_compute_dtype=torch.float16,
68+ bnb_4bit_use_double_quant=True
69+ )
70+ 
71+ self.model = AutoModelForCausalLM.from_pretrained(
72+ self.args.model_path,
73+ quantization_config=bnb_config if self.args.use_4bit else None,
74+ torch_dtype=torch.bfloat16 if self.args.use_bf16 else torch.float16,
75+ trust_remote_code=True,
76+ )
77+ 
78+ logger.info(f"Moving model to {self.args.device_type}...")
79+ self.model = self.model.to(self.args.device_type)
80+ 
81+ self.tokenizer = AutoTokenizer.from_pretrained(
82+ self.args.model_path,
83+ trust_remote_code=True
84+ )
85+ 
86+ if self.tokenizer.pad_token is None:
87+ self.tokenizer.pad_token = self.tokenizer.eos_token
88+ self.model.config.pad_token_id = self.tokenizer.eos_token_id
89+ 
90+ if self.args.gradient_checkpointing:
91+ self.model.gradient_checkpointing_enable()
92+ self.model.config.use_cache = False
93+ 
94+ 
95+ def apply_lora(self):
96+ if not self.args.use_lora:
97+ return
98+ 
99+ logger.info("Applying LoRA configuration...")
100+ 
101+ if self.args.use_4bit:
102+ self.model = prepare_model_for_kbit_training(self.model)
103+ 
104+ lora_config = LoraConfig(
105+ task_type=TaskType.CAUSAL_LM,
106+ r=self.args.lora_r,
107+ lora_alpha=self.args.lora_alpha,
108+ lora_dropout=self.args.lora_dropout,
109+ target_modules=self.get_lora_target_modules(),
110+ bias="none",
111+ )
112+ 
113+ self.model = get_peft_model(self.model, lora_config)
114+ self.model.print_trainable_parameters()
115+ 
116+ if self.args.enable_compile:
117+ self.model = torch.compile(self.model, dynamic=False)
118+ 
119+ 
120+ def get_lora_target_modules(self):
121+ target_modules = [
122+ "query_key_value",
123+ "dense",
124+ "dense_h_to_4h",
125+ "dense_4h_to_h",
126+ ]
127+ 
128+ model_modules = sorted([name for name, _ in self.model.named_modules()])
129+ available_modules = []
130+ 
131+ for target in target_modules:
132+ found = False
133+ for name in model_modules:
134+ if target in name:
135+ available_modules.append(name)
136+ found = True
137+ break
138+ if not found:
139+ logger.warning(f"Target module {target} not found in model")
140+ 
141+ available_modules = list(dict.fromkeys(available_modules))
142+ 
143+ if not available_modules:
144+ available_modules = ["qkv", "proj", "fc1", "fc2"]
145+ logger.warning(f"No avaliable, GLM-4 using LoRA target modules: {available_modules}")
146+ else:
147+ logger.info(f"GLM-4 LoRA target modules: {available_modules}")
148+ 
149+ return available_modules
150+ 
151+ 
152+ def load_and_preprocess_data(self) -> Dataset:
153+ logger.info(f"Loading dataset from {self.args.data_path}")
154+ 
155+ if self.args.data_path.endswith('.json') or self.args.data_path.endswith('.jsonl'):
156+ with open(self.args.data_path, 'r', encoding='utf-8') as f:
157+ if self.args.data_path.endswith('.jsonl'):
158+ data = [json.loads(line) for line in f]
159+ else:
160+ data = json.load(f)
161+ 
162+ formatted_data = []
163+ for item in data:
164+ if "conversations" in item or "messages" in item:
165+ messages = item.get("messages", item.get("conversations", []))
166+ text = self.tokenizer.apply_chat_template(
167+ messages,
168+ tokenize=False,
169+ add_generation_prompt=False
170+ )
171+ else:
172+ text = item.get("text", "")
173+ 
174+ formatted_data.append({"text": text})
175+ 
176+ dataset = Dataset.from_list(formatted_data)
177+ else:
178+ try:
179+ dataset = load_dataset(
180+ self.args.data_path,
181+ split=self.args.split
182+ )
183+ except:
184+ dataset = load_dataset(
185+ "json",
186+ data_files=self.args.data_path,
187+ split="train"
188+ )
189+ 
190+ tokenizer_ref = self.tokenizer
191+ max_length_ref = self.args.max_length
192+ 
193+ def preprocess_function(examples):
194+ tokenized = tokenizer_ref(
195+ examples["text"],
196+ truncation=True,
197+ padding="max_length" if self.args.pad_to_max_length else False,
198+ max_length=max_length_ref,
199+ return_tensors=None,
200+ return_attention_mask=True,
201+ )
202+ import copy
203+ tokenized["labels"] = copy.deepcopy(tokenized["input_ids"])
204+ return tokenized
205+ 
206+ 
207+ num_proc = self.args.num_proc if self.args.num_proc > 0 else None
208+ processed_dataset = dataset.map(
209+ preprocess_function,
210+ batched=True,
211+ remove_columns=dataset.column_names,
212+ num_proc=num_proc,
213+ load_from_cache_file=not self.args.overwrite_cache
214+ )
215+ logger.info(f"Dataset size: {len(processed_dataset)}")
216+ return processed_dataset
217+ 
218+ 
219+ def create_trainer(self, train_dataset, eval_dataset=None):
220+ has_eval = eval_dataset is not None
221+ eval_strategy = "steps" if has_eval else "no"
222+ save_strategy = "steps"
223+ 
224+ training_args = TrainingArguments(
225+ output_dir=self.args.output_dir,
226+ overwrite_output_dir=True,
227+ num_train_epochs=self.args.num_epochs,
228+ max_steps=self.args.max_steps if self.args.max_steps > 0 else 30,
229+ per_device_train_batch_size=self.args.batch_size,
230+ per_device_eval_batch_size=self.args.batch_size,
231+ gradient_accumulation_steps=self.args.gradient_accumulation_steps,
232+ weight_decay=self.args.weight_decay,
233+ logging_dir=f"{self.args.output_dir}/logs",
234+ logging_steps=self.args.logging_steps,
235+ save_steps=self.args.save_steps,
236+ save_total_limit=self.args.save_total_limit,
237+ eval_strategy=eval_strategy,
238+ eval_steps=self.args.eval_steps if has_eval else None,
239+ save_strategy=save_strategy,
240+ load_best_model_at_end=has_eval,
241+ metric_for_best_model="eval_loss",
242+ greater_is_better=False,
243+ learning_rate=self.args.learning_rate,
244+ lr_scheduler_type=self.args.lr_scheduler_type,
245+ fp16=self.args.use_fp16,
246+ bf16=self.args.use_bf16,
247+ gradient_checkpointing=self.args.gradient_checkpointing,
248+ report_to="none",
249+ ddp_find_unused_parameters=False if torch.cuda.device_count() > 1 else None,
250+ remove_unused_columns=False,
251+ dataloader_num_workers=self.args.dataloader_num_workers,
252+ group_by_length=self.args.group_by_length,
253+ length_column_name="length",
254+ prediction_loss_only=True,
255+ )
256+ 
257+ data_collator = DataCollatorForLanguageModeling(
258+ tokenizer=self.tokenizer,
259+ mlm=False,
260+ )
261+ 
262+ mod='compile' if self.args.enable_compile else 'eager'
263+ prof=None
264+ 
265+ if self.args.enable_profiler:
266+ profiling_save_path = self.args.profiler_save_path + '/' + model_name + '/' + mod
267+ prof = get_profile(self.args.profiler_start_step, self.args.profiler_end_step, profiling_save_path)
268+ 
269+ timing_callback = TimingCallback(prof, mod)
270+ 
271+ trainer = CustomTrainer(
272+ model=self.model,
273+ args=training_args,
274+ train_dataset=train_dataset,
275+ eval_dataset=eval_dataset,
276+ tokenizer=self.tokenizer,
277+ data_collator=data_collator,
278+ callbacks=[timing_callback],
279+ )
280+ return trainer
281+ 
282+ 
283+ def train(self):
284+ logger.info("Starting GLM-4 training...")
285+ 
286+ if self.args.use_lora:
287+ self.apply_lora()
288+ 
289+ dataset = self.load_and_preprocess_data()
290+ 
291+ if self.args.validation_split > 0:
292+ split_dataset = dataset.train_test_split(
293+ test_size=self.args.validation_split,
294+ seed=self.args.seed
295+ )
296+ train_dataset = split_dataset["train"]
297+ eval_dataset = split_dataset["test"]
298+ else:
299+ train_dataset = dataset
300+ eval_dataset = None
301+ 
302+ trainer = self.create_trainer(train_dataset, eval_dataset)
303+ train_result = trainer.train()
304+ if self.args.enable_compile:
305+ headers, values = torch._dynamo.utils.compile_times("csv")
306+ for header, value in zip(headers, values):
307+ if header == "PyCodeCache.load_by_key_path":
308+ numbers = [float(num.strip()) for num in value.split(',') if num.strip()]
309+ op_compile_time = sum(numbers)
310+ print(f"op_compile_time:{op_compile_time * 1e3} ms", )
311+ 
312+ trainer.save_model()
313+ self.tokenizer.save_pretrained(self.args.output_dir)
314+ metrics = train_result.metrics
315+ trainer.log_metrics("train", metrics)
316+ trainer.save_metrics("train", metrics)
317+ trainer.save_state()
318+ logger.info(f"Training completed! Model saved to {self.args.output_dir}")
319+ return metrics
320+ 
321+ 
322+def main():
323+ parser = argparse.ArgumentParser(description="Train GLM-4 model")
324+ parser.add_argument("--model_path", type=str, default="ZhipuAI/glm-4-9b-chat",
325+ help="Path to the pretrained GLM-4 model")
326+ parser.add_argument("--data_path", type=str, required=True,
327+ help="Path to training data (json/jsonl file or dataset name)")
328+ parser.add_argument("--output_dir", type=str, default="./glm4-finetuned",
329+ help="Output directory for trained model")
330+ parser.add_argument("--num_epochs", type=int, default=3,
331+ help="Number of training epochs")
332+ parser.add_argument("--batch_size", type=int, default=2,
333+ help="Batch size per device")
334+ parser.add_argument("--gradient_accumulation_steps", type=int, default=1,
335+ help="Gradient accumulation steps")
336+ parser.add_argument("--learning_rate", type=float, default=1e-4,
337+ help="Learning rate")
338+ parser.add_argument("--warmup_steps", type=int, default=50,
339+ help="Warmup steps")
340+ parser.add_argument("--max_steps", type=int, default=-1,
341+ help="Total training steps ")
342+ parser.add_argument("--weight_decay", type=float, default=0.01,
343+ help="Weight decay")
344+ parser.add_argument("--max_length", type=int, default=2048,
345+ help="Maximum sequence length")
346+ parser.add_argument("--lr_scheduler_type", type=str, default="cosine",
347+ choices=["linear", "cosine", "cosine_with_restarts", "constant"],
348+ help="Learning rate scheduler type")
349+ parser.add_argument("--use_lora", action="store_true",
350+ help="Use LoRA for parameter-efficient fine-tuning")
351+ parser.add_argument("--lora_r", type=int, default=8,
352+ help="LoRA rank")
353+ parser.add_argument("--lora_alpha", type=int, default=32,
354+ help="LoRA alpha")
355+ parser.add_argument("--lora_dropout", type=float, default=0.1,
356+ help="LoRA dropout")
357+ parser.add_argument("--use_4bit", action="store_true",
358+ help="Use 4-bit quantization")
359+ parser.add_argument("--use_fp16", action="store_true",
360+ help="Use FP16 precision")
361+ parser.add_argument("--use_bf16", action="store_true",
362+ help="Use BF16 precision")
363+ parser.add_argument("--gradient_checkpointing", action="store_true",
364+ help="Enable gradient checkpointing")
365+ parser.add_argument("--validation_split", type=float, default=0.1,
366+ help="Validation split ratio")
367+ parser.add_argument("--split", type=str, default="train",
368+ help="Dataset split to use")
369+ parser.add_argument("--num_proc", type=int, default=0,
370+ help="Number of processes for data preprocessing (0 = single process)")
371+ parser.add_argument("--pad_to_max_length", action="store_true",
372+ help="Pad sequences to max_length")
373+ parser.add_argument("--overwrite_cache", action="store_true",
374+ help="Overwrite cached features")
375+ parser.add_argument("--group_by_length", action="store_true",
376+ help="Group sequences by length for efficient training")
377+ parser.add_argument("--dataloader_num_workers", type=int, default=4,
378+ help="Number of workers for data loading")
379+ parser.add_argument("--seed", type=int, default=42,
380+ help="Random seed")
381+ parser.add_argument("--logging_steps", type=int, default=1,
382+ help="Log every X updates steps")
383+ parser.add_argument("--save_steps", type=int, default=500,
384+ help="Save checkpoint every X updates steps")
385+ parser.add_argument("--eval_steps", type=int, default=500,
386+ help="Evaluate every X updates steps")
387+ parser.add_argument("--save_total_limit", type=int, default=3,
388+ help="Limit the total amount of checkpoints")
389+ parser.add_argument("--report_to_tensorboard", action="store_true",
390+ help="Report metrics to TensorBoard")
391+ parser.add_argument("--enable_compile", action="store_true",
392+ help="Enable torch.compile and Inductor backend")
393+ parser.add_argument("--enable_profiler", action="store_true",
394+ help="Enable profiler for performance analysis")
395+ parser.add_argument("--profiler_start_step", type=int, default=5,
396+ help="Output directory for trained model")
397+ parser.add_argument("--profiler_end_step", type=int, default=8,
398+ help="Output directory for trained model")
399+ parser.add_argument("--profiler_save_path", type=str, default="./profile",
400+ help="Output directory for trained model")
401+ parser.add_argument("--npu-backend", type=str, default="mlir")
402+ parser.add_argument("--mfusion", action="store_true", help="Enable MFusion for graph fusion optimization")
403+ args = parser.parse_args()
404+ torch.manual_seed(args.seed)
405+ args.device_type = detect_device_type()
406+ os.environ['TORCHINDUCTOR_NPU_BACKEND']=args.npu_backend
407+ if args.npu_backend == "akg":
408+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
409+ os.environ['TORCHINDUCTOR_USE_AKG'] = '1'
410+ if args.mfusion:
411+ os.environ['TORCHINDUCTOR_ENABLE_MFUSION']='1'
412+ print(f"{args.device_type} train {model_name}")
413+ 
414+ trainer = GLM4Trainer(args)
415+ metrics = trainer.train()
416+ 
417+ print("\n" + "="*50)
418+ print("GLM-4 Training completed successfully!")
419+ print(f"Model saved to: {args.output_dir}")
420+ print(f"Final training loss: {metrics.get('train_loss', 'N/A')}")
421+ print("="*50)
422+ 
423+if __name__ == "__main__":
424+ main()
Abenchmarks/llm/llama3&llama3.2/README.md+120-0
@@ -0,0 +1,120 @@
1+# llama3&llama3.2 微调训练
2+ 
3+本 README 说明如何使用 **llama3-8B & llama3.2-3B** 模型权重,结合 **LlamaFactory** 提供的 `c4_demo.jsonl` 示例数据,完成数据下载、预处理与训练启动(含 eager / torch.compile 两种模式)。
4+ 
5+---
6+ 
7+## 目录
8+ 
9+- [1. 模型权重](#1-模型权重)
10+- [2. 数据获取](#2-数据获取)
11+- [3. 数据预处理](#3-数据预处理)
12+- [4. 模型训练](#4-模型训练)
13+ - [4.1 eager mode(默认)](#41-eager-mode默认)
14+ - [4.2 启用 torchcompile(可选)](#42-启用-torchcompile可选)
15+ - [4.3 采集profile文件(可选)](#43-采集profile文件可选)
16+ 
17+---
18+ 
19+## 1. 模型权重
20+ 
21+- ModelScope 模型:**llama3-8B**
22+ https://modelscope.cn/models/LLM-Research/Meta-Llama-3-8B
23+ 
24+- ModelScope 模型:**llama3.2-3B**
25+ https://modelscope.cn/models/LLM-Research/Llama-3.2-3B
26+ 
27+可在链接页面中模型文件一栏直接下载模型,或使用ModelScope官方推荐SDK下载方式:
28+ 
29+```bash
30+#llama3-8B
31+from modelscope import snapshot_download
32+model_dir = snapshot_download('LLM-Research/Meta-Llama-3-8B')
33+ 
34+ 
35+#llama3.2-3B
36+from modelscope import snapshot_download
37+model_dir = snapshot_download('LLM-Research/Llama-3.2-3B')
38+```
39+ 
40+### 环境提示
41+ 
42+本项目依赖已整理到 `requirements.txt`,可直接安装:
43+ 
44+```bash
45+pip install -r ../utils/requirements.txt
46+```
47+ 
48+## 2. 数据获取
49+ 
50+训练数据集来自 LlamaFactory 仓库示例数据,可直接在如下连接获取:
51+ 
52+- `c4_demo.json`
53+ https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
54+ 
55+或直接下载 raw 文件到本地:
56+ 
57+```bash
58+wget -O c4_demo.json \
59+https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
60+```
61+ 
62+## 3. 数据预处理
63+ 
64+`train_llama3.py`中已经对数据进行了处理, 本脚本支持对 `llama3-8B``Llama-3.2-3B`预训练,在训练时通过`--model_path`修改模型权重路径即可
65+ 
66+## 4. 模型训练
67+ 
68+训练脚本:`run_llama3.sh`,脚本支持在 GPU 和 NPU 训练
69+ 
70+开始训练前,请修改脚本中的路径参数:
71+ 
72+- 模型权重路径
73+- 训练数据路径
74+ 
75+### 4.1 eager mode(默认)
76+ 
77+```bash
78+bash run_llama3.sh
79+```
80+ 
81+### 4.2 启用 `torch.compile`(可选)
82+ 
83+可通过添加 `--enable_compile` 选项运行图模式
84+当在 GPU 上训练时,默认后端使用triton;当在 NPU 上训练时,可进一步指定后端为 mlir 或 dvm,默认使用 mlir。
85+ 
86+**默认后端(mlir,可不写 --npu-backend):**
87+ 
88+```bash
89+bash run_llama3.sh \
90+ --enable_compile
91+```
92+ 
93+**显式指定后端为 mlir:**
94+ 
95+```bash
96+bash run_llama3.sh \
97+ --enable_compile \
98+ --npu-backend mlir
99+```
100+ 
101+**切换后端为 dvm::**
102+ 
103+```bash
104+bash run_llama3.sh \
105+ --enable_compile \
106+ --npu-backend dvm
107+```
108+ 
109+### 4.3 采集profile文件(可选)
110+ 
111+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
112+ 
113+```bash
114+bash run_llama3.sh \
115+ --enable_profiler \
116+ --profiler_start_step 5 \
117+ --profiler_end_step 6 \
118+```
119+ 
120+可以通过 `--profiler_start_step``--profiler_end_step` 分别设置profile开始和结束步数。
Abenchmarks/llm/llama3&llama3.2/run_llama3.sh+21-0
@@ -0,0 +1,21 @@
1+export TORCHINDUCTOR_CACHE_DIR='./cache'
2+export ASCEND_RT_VISIBLE_DEVICES=3
3+export TORCH_COMPILE_DEBUG=1
4+export TORCH_NPU_USE_COMPATIBLE_IMPL=1
5+ 
6+rm -rf ./cache/*
7+mkdir -p ./cache logs
8+ 
9+python train_llama3.py \
10+ --model_path "your model path" \
11+ --model_name "your model name" \
12+ --data_path "dataset path" \
13+ --output_dir "./llama3-finetuned" \
14+ --num_epochs 3 \
15+ --max_steps 200 \
16+ --batch_size 1 \
17+ --learning_rate 2e-5 \
18+ --max_length 512 \
19+ --use_lora \
20+ --use_bf16 \
21+ --pad_to_max_length > logs/train_llama3.log 2>&1
Abenchmarks/llm/llama3&llama3.2/train_llama3.py+387-0
@@ -0,0 +1,387 @@
1+import torch
2+import sys
3+import os
4+from pathlib import Path
5+import torch.nn as nn
6+from datasets import Dataset, load_dataset
7+from transformers import (
8+ AutoModelForCausalLM,
9+ AutoTokenizer,
10+ TrainingArguments,
11+ Trainer,
12+ DataCollatorForLanguageModeling,
13+ get_linear_schedule_with_warmup,
14+ BitsAndBytesConfig,
15+ TrainerCallback
16+)
17+from peft import (
18+ LoraConfig,
19+ get_peft_model,
20+ prepare_model_for_kbit_training,
21+ TaskType
22+)
23+import json
24+from typing import Dict, List, Optional
25+import argparse
26+import logging
27+ 
28+sys.path.append(str(Path(__file__).parent.parent))
29+from utils.utils import (
30+ TimingCallback,
31+ get_profile,
32+ detect_device_type
33+)
34+ 
35+logging.basicConfig(level=logging.INFO)
36+logger = logging.getLogger(__name__)
37+ 
38+class LLama3Trainer:
39+ def __init__(self, args):
40+ self.args = args
41+ self.setup_training()
42+ 
43+ def setup_training(self):
44+ logger.info(f"Loading model from {self.args.model_path}")
45+ 
46+ bnb_config = None
47+ if self.args.use_4bit:
48+ bnb_config = BitsAndBytesConfig(
49+ load_in_4bit=True,
50+ bnb_4bit_quant_type="nf4",
51+ bnb_4bit_compute_dtype=torch.float16,
52+ bnb_4bit_use_double_quant=True
53+ )
54+ 
55+ self.model = AutoModelForCausalLM.from_pretrained(
56+ self.args.model_path,
57+ quantization_config=bnb_config if self.args.use_4bit else None,
58+ torch_dtype=torch.bfloat16 if self.args.use_bf16 else torch.float32,
59+ trust_remote_code=True
60+ )
61+ 
62+ logger.info(f"Moving model to {self.args.device_type}...")
63+ self.model = self.model.to(self.args.device_type)
64+ self.tokenizer = AutoTokenizer.from_pretrained(
65+ self.args.model_path,
66+ trust_remote_code=True
67+ )
68+ 
69+ if self.tokenizer.pad_token is None:
70+ self.tokenizer.pad_token = self.tokenizer.eos_token
71+ self.model.config.pad_token_id = self.tokenizer.eos_token_id
72+ 
73+ if self.args.gradient_checkpointing:
74+ self.model.gradient_checkpointing_enable()
75+ self.model.config.use_cache = False
76+ 
77+ 
78+ def apply_lora(self):
79+ if not self.args.use_lora:
80+ return
81+ 
82+ logger.info("Applying LoRA configuration...")
83+ if self.args.use_4bit:
84+ self.model = prepare_model_for_kbit_training(self.model)
85+ 
86+ lora_config = LoraConfig(
87+ task_type=TaskType.CAUSAL_LM,
88+ r=self.args.lora_r,
89+ lora_alpha=self.args.lora_alpha,
90+ lora_dropout=self.args.lora_dropout,
91+ target_modules=self.get_lora_target_modules(),
92+ bias="none",
93+ )
94+ 
95+ self.model = get_peft_model(self.model, lora_config)
96+ self.model.print_trainable_parameters()
97+ 
98+ if self.args.enable_compile:
99+ self.model = torch.compile(self.model, dynamic=False)
100+ 
101+ def get_lora_target_modules(self):
102+ target_modules = [
103+ "q_proj", "k_proj", "v_proj", "o_proj",
104+ "gate_proj", "up_proj", "down_proj",
105+ ]
106+ 
107+ model_modules = set([name for name, _ in self.model.named_modules()])
108+ available_modules = [m for m in target_modules if any(m in name for name in model_modules)]
109+ 
110+ if not available_modules:
111+ available_modules = ["qkv_proj", "dense", "fc1", "fc2"]
112+ 
113+ logger.info(f"Using LoRA target modules: {available_modules}")
114+ return available_modules
115+ 
116+ def load_and_preprocess_data(self) -> Dataset:
117+ logger.info(f"Loading dataset from {self.args.data_path}")
118+ 
119+ if self.args.data_path.endswith('.json') or self.args.data_path.endswith('.jsonl'):
120+ with open(self.args.data_path, 'r', encoding='utf-8') as f:
121+ if self.args.data_path.endswith('.jsonl'):
122+ data = [json.loads(line) for line in f]
123+ else:
124+ data = json.load(f)
125+ 
126+ formatted_data = []
127+ for item in data:
128+ if "conversations" in item:
129+ conversations = item["conversations"]
130+ text = self.format_conversation(conversations)
131+ elif "messages" in item:
132+ messages = item["messages"]
133+ text = self.tokenizer.apply_chat_template(
134+ messages,
135+ tokenize=False,
136+ add_generation_prompt=False
137+ )
138+ else:
139+ text = item.get("text", "")
140+ 
141+ formatted_data.append({"text": text})
142+ 
143+ dataset = Dataset.from_list(formatted_data)
144+ else:
145+ try:
146+ dataset = load_dataset(
147+ self.args.data_path,
148+ split=self.args.split
149+ )
150+ except:
151+ dataset = load_dataset(
152+ "json",
153+ data_files=self.args.data_path,
154+ split="train"
155+ )
156+ 
157+ def preprocess_function(examples, tokenizer=self.tokenizer, max_length=self.args.max_length):
158+ tokenized = tokenizer(
159+ examples["text"],
160+ truncation=True,
161+ padding="max_length",
162+ max_length=max_length,
163+ return_tensors=None,
164+ return_attention_mask=True,
165+ )
166+ import copy
167+ tokenized["labels"] = copy.deepcopy(tokenized["input_ids"])
168+ return tokenized
169+ 
170+ num_proc = self.args.num_proc if self.args.num_proc > 0 else None
171+ processed_dataset = dataset.map(
172+ preprocess_function,
173+ batched=True,
174+ remove_columns=dataset.column_names,
175+ num_proc=num_proc,
176+ load_from_cache_file=not self.args.overwrite_cache
177+ )
178+ 
179+ logger.info(f"Dataset size: {len(processed_dataset)}")
180+ return processed_dataset
181+ 
182+ def format_conversation(self, conversations: List[Dict]) -> str:
183+ formatted_text = ""
184+ 
185+ for turn in conversations:
186+ role = turn.get("from", "").lower()
187+ content = turn.get("value", "")
188+ if role == "human" or role == "user":
189+ formatted_text += f"<|im_start|>user\n{content}<|im_end|>\n"
190+ elif role == "gpt" or role == "assistant":
191+ formatted_text += f"<|im_start|>assistant\n{content}<|im_end|>\n"
192+ elif role == "system":
193+ formatted_text += f"<|im_start|>system\n{content}<|im_end|>\n"
194+ 
195+ return formatted_text
196+ 
197+ def create_trainer(self, train_dataset, eval_dataset=None):
198+ has_eval = eval_dataset is not None
199+ eval_strategy = "steps" if has_eval else "no"
200+ save_strategy = "steps" if has_eval else "steps"
201+ 
202+ training_args = TrainingArguments(
203+ output_dir=self.args.output_dir,
204+ overwrite_output_dir=True,
205+ num_train_epochs=self.args.num_epochs,
206+ max_steps=self.args.max_steps,
207+ per_device_train_batch_size=self.args.batch_size,
208+ per_device_eval_batch_size=self.args.batch_size,
209+ gradient_accumulation_steps=self.args.gradient_accumulation_steps,
210+ weight_decay=self.args.weight_decay,
211+ logging_dir=f"{self.args.output_dir}/logs",
212+ logging_steps=self.args.logging_steps,
213+ save_steps=self.args.save_steps,
214+ save_total_limit=self.args.save_total_limit,
215+ eval_strategy=eval_strategy,
216+ eval_steps=self.args.eval_steps if has_eval else None,
217+ save_strategy=save_strategy,
218+ load_best_model_at_end=has_eval,
219+ metric_for_best_model="eval_loss",
220+ greater_is_better=False,
221+ learning_rate=self.args.learning_rate,
222+ lr_scheduler_type="cosine",
223+ fp16=self.args.use_fp16,
224+ bf16=self.args.use_bf16,
225+ gradient_checkpointing=self.args.gradient_checkpointing,
226+ report_to="none",
227+ ddp_find_unused_parameters=False if torch.cuda.device_count() > 1 else None,
228+ remove_unused_columns=False,
229+ )
230+ data_collator = DataCollatorForLanguageModeling(
231+ tokenizer=self.tokenizer,
232+ mlm=False,
233+ )
234+ mod='compile' if self.args.enable_compile else 'eager'
235+ prof=None
236+ 
237+ if self.args.enable_profiler:
238+ profiling_save_path = self.args.profiler_save_path + '/' + self.args.model_name + '/' + mod
239+ prof = get_profile(self.args.profiler_start_step, self.args.profiler_end_step, profiling_save_path)
240+ 
241+ timing_callback = TimingCallback(prof, mod)
242+ 
243+ trainer = Trainer(
244+ model=self.model,
245+ args=training_args,
246+ train_dataset=train_dataset,
247+ eval_dataset=eval_dataset,
248+ tokenizer=self.tokenizer,
249+ data_collator=data_collator,
250+ callbacks=[timing_callback],
251+ )
252+ return trainer
253+ 
254+ def train(self):
255+ logger.info("Starting training...")
256+ 
257+ if self.args.use_lora:
258+ self.apply_lora()
259+ 
260+ dataset = self.load_and_preprocess_data()
261+ if self.args.validation_split > 0:
262+ split_dataset = dataset.train_test_split(
263+ test_size=self.args.validation_split,
264+ seed=self.args.seed
265+ )
266+ train_dataset = split_dataset["train"]
267+ eval_dataset = split_dataset["test"]
268+ else:
269+ train_dataset = dataset
270+ eval_dataset = None
271+ 
272+ trainer = self.create_trainer(train_dataset, eval_dataset)
273+ train_result = trainer.train()
274+ if self.args.enable_compile:
275+ headers, values = torch._dynamo.utils.compile_times("csv")
276+ for header, value in zip(headers, values):
277+ if header == "PyCodeCache.load_by_key_path":
278+ numbers = [float(num.strip()) for num in value.split(',') if num.strip()]
279+ op_compile_time = sum(numbers)
280+ print(f"op_compile_time:{op_compile_time * 1e3} ms", )
281+ 
282+ trainer.save_model()
283+ self.tokenizer.save_pretrained(self.args.output_dir)
284+ 
285+ metrics = train_result.metrics
286+ trainer.log_metrics("train", metrics)
287+ trainer.save_metrics("train", metrics)
288+ trainer.save_state()
289+ logger.info(f"Training completed! Model saved to {self.args.output_dir}")
290+ return metrics
291+ 
292+ 
293+def main():
294+ parser = argparse.ArgumentParser(description="Train Qwen3 model")
295+ parser.add_argument("--model_path", type=str, required=True,
296+ help="Path to the pretrained model")
297+ parser.add_argument("--data_path", type=str, required=True,
298+ help="Path to training data (json/jsonl file or dataset name)")
299+ parser.add_argument("--output_dir", type=str, default="./llama3-finetuned",
300+ help="Output directory for trained model")
301+ parser.add_argument("--num_epochs", type=int, default=3,
302+ help="Number of training epochs")
303+ parser.add_argument("--batch_size", type=int, default=4,
304+ help="Batch size per device")
305+ parser.add_argument("--gradient_accumulation_steps", type=int, default=2,
306+ help="Gradient accumulation steps")
307+ parser.add_argument("--learning_rate", type=float, default=2e-4,
308+ help="Learning rate")
309+ parser.add_argument("--warmup_steps", type=int, default=5,
310+ help="Warmup steps")
311+ parser.add_argument("--max_steps", type=int, default=1,
312+ help="Total training steps")
313+ parser.add_argument("--weight_decay", type=float, default=0.01,
314+ help="Weight decay")
315+ parser.add_argument("--max_length", type=int, default=2048,
316+ help="Maximum sequence length")
317+ parser.add_argument("--use_lora", action="store_true",
318+ help="Use LoRA for parameter-efficient fine-tuning")
319+ parser.add_argument("--lora_r", type=int, default=8,
320+ help="LoRA rank")
321+ parser.add_argument("--lora_alpha", type=int, default=32,
322+ help="LoRA alpha")
323+ parser.add_argument("--lora_dropout", type=float, default=0.1,
324+ help="LoRA dropout")
325+ parser.add_argument("--use_4bit", action="store_true",
326+ help="Use 4-bit quantization")
327+ parser.add_argument("--use_fp16", action="store_true",
328+ help="Use FP16 precision")
329+ parser.add_argument("--use_bf16", action="store_true",
330+ help="Use BF16 precision")
331+ parser.add_argument("--gradient_checkpointing", action="store_true",
332+ help="Enable gradient checkpointing")
333+ parser.add_argument("--validation_split", type=float, default=0.1,
334+ help="Validation split ratio")
335+ parser.add_argument("--split", type=str, default="train",
336+ help="Dataset split to use")
337+ parser.add_argument("--num_proc", type=int, default=0,
338+ help="Number of processes for data preprocessing (0 = single process, avoid CUDA conflict)")
339+ parser.add_argument("--pad_to_max_length", action="store_true",
340+ help="Pad sequences to max_length")
341+ parser.add_argument("--overwrite_cache", action="store_true",
342+ help="Overwrite cached features")
343+ parser.add_argument("--seed", type=int, default=42,
344+ help="Random seed")
345+ parser.add_argument("--logging_steps", type=int, default=1,
346+ help="Log every X updates steps")
347+ parser.add_argument("--save_steps", type=int, default=500,
348+ help="Save checkpoint every X updates steps")
349+ parser.add_argument("--eval_steps", type=int, default=500,
350+ help="Evaluate every X updates steps")
351+ parser.add_argument("--save_total_limit", type=int, default=3,
352+ help="Limit the total amount of checkpoints")
353+ parser.add_argument("--enable_compile", action="store_true",
354+ help="Enable torch.compile and Inductor backend")
355+ parser.add_argument("--enable_profiler", action="store_true",
356+ help="Enable profiler for performance analysis")
357+ parser.add_argument("--profiler_start_step", type=int, default=5,
358+ help="Output directory for trained model")
359+ parser.add_argument("--profiler_end_step", type=int, default=8,
360+ help="Output directory for trained model")
361+ parser.add_argument("--profiler_save_path", type=str, default="./profile",
362+ help="Output directory for trained model")
363+ parser.add_argument("--npu-backend", type=str, default="mlir")
364+ parser.add_argument("--model_name", type=str, default="llama3-8B", help="your model name")
365+ parser.add_argument("--mfusion", action="store_true", help="Enable MFusion for graph fusion optimization")
366+ 
367+ args = parser.parse_args()
368+ torch.manual_seed(args.seed)
369+ 
370+ args.device_type = detect_device_type()
371+ os.environ['TORCHINDUCTOR_NPU_BACKEND']=args.npu_backend
372+ if args.npu_backend == "akg":
373+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
374+ os.environ['TORCHINDUCTOR_USE_AKG'] = '1'
375+ if args.mfusion:
376+ os.environ['TORCHINDUCTOR_ENABLE_MFUSION']='1'
377+ print(f"{args.device_type} train {args.model_name}")
378+ trainer = LLama3Trainer(args)
379+ metrics = trainer.train()
380+ print("\n" + "="*50)
381+ print("Training completed successfully!")
382+ print(f"Model saved to: {args.output_dir}")
383+ print(f"Final training loss: {metrics.get('train_loss', 'N/A')}")
384+ print("="*50)
385+ 
386+if __name__ == "__main__":
387+ main()