PEFT LoRA微调FLAN-T5遇No executable batch size found错误求助
问题排查与解决方案
问题背景
在Ubuntu 18.04LTS系统(配备8GB显存NVIDIA GPU)上,使用PEFT的LoRA方法微调Hugging Face的FLAN-T5-base模型时,触发以下错误:
RuntimeError: No executable batch size found, reached zero
以下是具体排查和解决方法。
错误信息(中文翻译)
找到缓存的数据集csv (/home/username/.cache/huggingface/datasets/knkarthick___csv/knkarthick--dialogsum-cd36827d3490488d/0.0.0/6954658bab30a358235fa864b05cf819af0e179325c740e4bc853bcc7ec513e1) 100%|██████████| 3/3 [00:00<00:00, 1134.31it/s] /home/username/anaconda3/envs/new_llm/lib/python3.10/site-packages/transformers/optimization.py:407: FutureWarning: 该AdamW实现已废弃,后续版本将移除。请使用PyTorch官方实现torch.optim.AdamW,或设置`no_deprecation_warning=True`关闭此警告 warnings.warn( 0%| | 0/16 [00:00<?, ?it/s] 0%| | 0/32 [00:00<?, ?it/s] 0%| | 0/63 [00:00<?, ?it/s] Traceback (most recent call last):it/s] File "/home/username/stuff/username_storage/LLM/PEFT/offline_peft_train_no_log_max_depth.py", line 161, in <module> peft_trainer.train() File "/home/username/anaconda3/envs/new_llm/lib/python3.10/site-packages/transformers/trainer.py", line 1664, in train return inner_training_loop( File "/home/username/anaconda3/envs/new_llm/lib/python3.10/site-packages/accelerate/utils/memory.py", line 134, in decorator raise RuntimeError("No executable batch size found, reached zero.") RuntimeError: No executable batch size found, reached zero. 0%| | 0/125 [00:00<?, ?it/s]
问题原因分析
- 预处理阶段提前占用GPU显存:在
tokenize_function中直接将input_ids和labels移至CUDA设备,导致数据集占用GPU显存,后续auto_find_batch_size调整批次时出现显存不足或设备不匹配问题。 - bfloat16兼容性不足:Ubuntu 18.04默认配套的CUDA版本多为10.x,而
torch.bfloat16需要Ampere架构以上GPU+CUDA 11.0及以上支持。若GPU为Turing(如RTX 20系列)或更早型号,无法原生支持bfloat16,会导致模型显存占用远超预期。 - 未限制序列长度:
tokenize_function使用padding="max_length"但未指定具体长度,默认padding到tokenizer最大长度(FLAN-T5默认512),进一步增加单样本显存占用。 - auto_find_batch_size机制局限:该参数会从大到小尝试批次大小,若初始显存已被过度占用,即使降到batch size=0仍无法运行,就会触发报错。
解决方案
1. 修正数据预处理逻辑
修改tokenize_function,移除.cuda()调用,让Trainer在训练阶段自动分发数据到设备,同时显式设置序列长度减少显存占用:
def tokenize_function(example): start_prompt = 'Summarize the following conversation.\n\n' end_prompt = '\n\nSummary: ' prompt = [start_prompt + dialogue + end_prompt for dialogue in example["dialogue"]] # 移除.cuda(),显式设置序列长度 example['input_ids'] = tokenizer(prompt, padding="max_length", truncation=True, max_length=384, return_tensors="pt").input_ids example['labels'] = tokenizer(example["summary"], padding="max_length", truncation=True, max_length=128, return_tensors="pt").input_ids return example
2. 替换bfloat16为float16并启用混合精度
适配旧CUDA/GPU环境,修改模型加载代码并开启混合精度训练:
original_model = AutoModelForSeq2SeqLM.from_pretrained(model_name, torch_dtype=torch.float16)
在TrainingArguments中添加混合精度配置:
peft_training_args = TrainingArguments( output_dir=output_dir, per_device_train_batch_size=2, # 手动设置小批次 learning_rate=1e-3, num_train_epochs=1, fp16=True # 启用混合精度训练 )
3. 关闭auto_find_batch_size,手动配置批次与梯度累积
若8GB显存仍无法运行batch size=2,可降为1并配合梯度累积弥补批次大小:
peft_training_args = TrainingArguments( output_dir=output_dir, per_device_train_batch_size=1, gradient_accumulation_steps=4, # 累积4步等效于batch size=4 learning_rate=1e-3, num_train_epochs=1, fp16=True )
4. 额外显存优化(可选)
- 启用梯度检查点:进一步降低显存占用
original_model = AutoModelForSeq2SeqLM.from_pretrained(model_name, torch_dtype=torch.float16, gradient_checkpointing=True) - 训练前清理GPU缓存:
torch.cuda.empty_cache()
内容的提问来源于stack exchange,提问作者user3476463
相关产品推荐
相关产品推荐

