当前位置: 首页 > news >正文

用 LoRA 对 Qwen2.5-VL 模型进行SFT - FORCE_TORCHRUN=1

用 LoRA 对 Qwen2.5-VL 模型进行SFT - FORCE_TORCHRUN=1

flyfish

qwen2_5vl_lora_sft.yaml
│    │   │    │    └── SFT: 有监督微调 (Supervised Fine-Tuning)
│    │   │    └── LoRA: 低秩适应 (Low-Rank Adaptation)
│    │   └── VL: 视觉语言 (Vision-Language)
│    └── 2_5: Qwen2.5 模型
└── Qwen: (Qwen) 模型系列

FORCE_TORCHRUN=1

FORCE_TORCHRUN=1 llamafactory-cli train examples/train_lora/qwen2_5vl_lora_sft.yaml

FORCE_TORCHRUN=1 的核心作用是:
强制分布式训练:无论 GPU 数量,确保训练在分布式环境下运行。
兼容 DeepSpeed/LoRA:满足内存优化和参数高效微调的环境要求。
自动化参数配置:自动设置 torchrun 所需的节点、端口等参数。

1. 命令行层面的作用

FORCE_TORCHRUN=1 llamafactory-cli train examples/train_lora/qwen2_5vl_lora_sft.yaml

环境变量注入FORCE_TORCHRUN=1 将环境变量 FORCE_TORCHRUN 的值设为 1,这会被 llamafactory-cli 脚本捕获。
命令解析llamafactory-cli train ... 触发训练流程,代码会检查 FORCE_TORCHRUN 是否存在,若存在则强制使用 torchrun 启动训练。

2. 代码层面的实现逻辑

在提供的代码中,关键判断逻辑如下:

if command == "train" and (is_env_enabled("FORCE_TORCHRUN") or (get_device_count() > 1 and not use_ray())):# 使用 torchrun 启动分布式训练# ... 代码省略 ...

双条件触发

  1. 显式指定:若 FORCE_TORCHRUN=1,无论 GPU 数量多少,都使用 torchrun
  2. 自动检测:若未指定 FORCE_TORCHRUN,但检测到多 GPU(get_device_count() > 1)且未使用 Ray 框架,也会自动使用 torchrun

3. LoRA 训练需要 FORCE_TORCHRUN=1

LoRA 微调通常需要:
分布式训练支持:即使单 GPU 也可能需要分布式环境(如 DeepSpeed ZeRO 优化)。
精确的梯度同步:分布式训练能确保多 GPU 间梯度计算的一致性。
内存优化:DeepSpeed 等工具依赖分布式初始化来实现参数分片和内存节省。

4. 执行流程详解

当你运行 FORCE_TORCHRUN=1 ... 时,代码会:

Step 1:环境变量检测
if is_env_enabled("FORCE_TORCHRUN"):# 准备分布式训练参数
Step 2:参数配置

自动设置以下关键参数(代码片段):

nnodes = os.getenv("NNODES", "1")               # 节点数,默认 1
node_rank = os.getenv("NODE_RANK", "0")         # 当前节点编号
nproc_per_node = os.getenv("NPROC_PER_NODE", ...)  # 每个节点的 GPU 数
master_addr = os.getenv("MASTER_ADDR", "127.0.0.1")  # 主节点地址
master_port = os.getenv("MASTER_PORT", ...)     # 主节点端口
Step 3:启动 torchrun(重点就在这里)
process = subprocess.run(("torchrun --nnodes {nnodes} --node_rank {node_rank} --nproc_per_node {nproc_per_node} ""--master_addr {master_addr} --master_port {master_port} {file_name} {args}").format(nnodes=nnodes,node_rank=node_rank,nproc_per_node=nproc_per_node,master_addr=master_addr,master_port=master_port,file_name=launcher.__file__,args=" ".join(sys.argv[1:]),).split(),env=env,check=True,
)

通过 subprocess.run 执行等效命令:

torchrun --nnodes=1 --node_rank=0 --nproc_per_node=8 \--master_addr=127.0.0.1 --master_port=29500 \/path/to/launcher.py train examples/train_lora/qwen2_5vl_lora_sft.yaml

参数解释
--nproc_per_node=8:使用 8 个 GPU(根据实际环境自动检测)。
launcher.py:内部训练脚本入口。

5. 与 DeepSpeed 的强依赖关系

代码中另一个关键检查:

if training_args.deepspeed and training_args.parallel_mode != ParallelMode.DISTRIBUTED:raise ValueError("Please use `FORCE_TORCHRUN=1` to launch DeepSpeed training.")

DeepSpeed 必须要求分布式环境:即使单 GPU 也需要通过 torchrun 初始化。
错误场景:若未设置 FORCE_TORCHRUN=1,直接使用 DeepSpeed 会触发此错误。

6. 应用

场景是否需要 FORCE_TORCHRUN=1
单 GPU + LoRA 微调可选(建议使用,确保兼容性)
多 GPU + LoRA 微调必须(自动触发或显式指定)
使用 DeepSpeed 优化必须(否则报错)
调试分布式训练代码推荐(模拟分布式环境)

在使用 llamafactory-cli 进行 LoRA 微调或 DeepSpeed 训练时,始终建议添加 FORCE_TORCHRUN=1,以避免分布式初始化错误。

代码参考


import os
import subprocess
import sys
from copy import deepcopy
from functools import partialUSAGE = ("-" * 70+ "\n"+ "| Usage:                                                             |\n"+ "|   llamafactory-cli api -h: launch an OpenAI-style API server       |\n"+ "|   llamafactory-cli chat -h: launch a chat interface in CLI         |\n"+ "|   llamafactory-cli eval -h: evaluate models                        |\n"+ "|   llamafactory-cli export -h: merge LoRA adapters and export model |\n"+ "|   llamafactory-cli train -h: train models                          |\n"+ "|   llamafactory-cli webchat -h: launch a chat interface in Web UI   |\n"+ "|   llamafactory-cli webui: launch LlamaBoard                        |\n"+ "|   llamafactory-cli version: show version info                      |\n"+ "-" * 70
)def main():from . import launcherfrom .api.app import run_apifrom .chat.chat_model import run_chatfrom .eval.evaluator import run_evalfrom .extras import loggingfrom .extras.env import VERSION, print_envfrom .extras.misc import find_available_port, get_device_count, is_env_enabled, use_rayfrom .train.tuner import export_model, run_expfrom .webui.interface import run_web_demo, run_web_uilogger = logging.get_logger(__name__)WELCOME = ("-" * 58+ "\n"+ f"| Welcome to LLaMA Factory, version {VERSION}"+ " " * (21 - len(VERSION))+ "|\n|"+ " " * 56+ "|\n"+ "| Project page: https://github.com/hiyouga/LLaMA-Factory |\n"+ "-" * 58)COMMAND_MAP = {"api": run_api,"chat": run_chat,"env": print_env,"eval": run_eval,"export": export_model,"train": run_exp,"webchat": run_web_demo,"webui": run_web_ui,"version": partial(print, WELCOME),"help": partial(print, USAGE),}command = sys.argv.pop(1) if len(sys.argv) > 1 else "help"if command == "train" and (is_env_enabled("FORCE_TORCHRUN") or (get_device_count() > 1 and not use_ray())):# launch distributed trainingnnodes = os.getenv("NNODES", "1")node_rank = os.getenv("NODE_RANK", "0")nproc_per_node = os.getenv("NPROC_PER_NODE", str(get_device_count()))master_addr = os.getenv("MASTER_ADDR", "127.0.0.1")master_port = os.getenv("MASTER_PORT", str(find_available_port()))logger.info_rank0(f"Initializing {nproc_per_node} distributed tasks at: {master_addr}:{master_port}")if int(nnodes) > 1:logger.info_rank0(f"Multi-node training enabled: num nodes: {nnodes}, node rank: {node_rank}")# elastic launch supportmax_restarts = os.getenv("MAX_RESTARTS", "0")rdzv_id = os.getenv("RDZV_ID")min_nnodes = os.getenv("MIN_NNODES")max_nnodes = os.getenv("MAX_NNODES")env = deepcopy(os.environ)if is_env_enabled("OPTIM_TORCH", "1"):# optimize DDP, see https://zhuanlan.zhihu.com/p/671834539env["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"env["TORCH_NCCL_AVOID_RECORD_STREAMS"] = "1"if rdzv_id is not None:# launch elastic job with fault tolerant support when possible# see also https://docs.pytorch.org/docs/stable/elastic/train_script.htmlrdzv_nnodes = nnodes# elastic number of nodes if MIN_NNODES and MAX_NNODES are setif min_nnodes is not None and max_nnodes is not None:rdzv_nnodes = f"{min_nnodes}:{max_nnodes}"process = subprocess.run(("torchrun --nnodes {rdzv_nnodes} --nproc-per-node {nproc_per_node} ""--rdzv-id {rdzv_id} --rdzv-backend c10d --rdzv-endpoint {master_addr}:{master_port} ""--max-restarts {max_restarts} {file_name} {args}").format(rdzv_nnodes=rdzv_nnodes,nproc_per_node=nproc_per_node,rdzv_id=rdzv_id,master_addr=master_addr,master_port=master_port,max_restarts=max_restarts,file_name=launcher.__file__,args=" ".join(sys.argv[1:]),).split(),env=env,check=True,)else:# NOTE: DO NOT USE shell=True to avoid security riskprocess = subprocess.run(("torchrun --nnodes {nnodes} --node_rank {node_rank} --nproc_per_node {nproc_per_node} ""--master_addr {master_addr} --master_port {master_port} {file_name} {args}").format(nnodes=nnodes,node_rank=node_rank,nproc_per_node=nproc_per_node,master_addr=master_addr,master_port=master_port,file_name=launcher.__file__,args=" ".join(sys.argv[1:]),).split(),env=env,check=True,)sys.exit(process.returncode)elif command in COMMAND_MAP:COMMAND_MAP[command]()else:print(f"Unknown command: {command}.\n{USAGE}")if __name__ == "__main__":from multiprocessing import freeze_supportfreeze_support()main()

DeepSpeed 是一个专为大规模分布式训练设计的优化库,必须在分布式环境下运行。即使只使用单 GPU,DeepSpeed 也需要通过 torchrun 或 torch.distributed.launch 来初始化必要的分布式通信环境。
而 FORCE_TORCHRUN=1 正是用于强制程序以分布式模式启动的标志。如果没有设置这个标志,程序可能以普通单进程模式运行,导致 DeepSpeed 初始化失败。

if training_args.deepspeed and training_args.parallel_mode != ParallelMode.DISTRIBUTED:raise ValueError("Please use `FORCE_TORCHRUN=1` to launch DeepSpeed training.")
http://www.xdnf.cn/news/970543.html

相关文章:

  • 条件运算符
  • error: src refspec master does not match any - Git
  • coze的基本使用
  • 从零开始搭建现代化 Monorepo 开发模板:TypeScript + Rollup + Jest + 持续集成完整指南
  • Git操作问题及解决方案-记录5
  • (十)学生端搭建
  • 【SQL学习笔记3】深入理解窗口函数的用法
  • 鹰盾加密器系统黑屏问题的深度解析与处理机制
  • RAG系统向量数据库选型与Prompt Engineering鲁棒性测试实践
  • 10:00开始面试,10:06就出来了,问的问题有点变态。。。
  • 第14篇:数据库中间件的分布式配置与动态路由规则热加载机制
  • vxe-table 如何实现直接渲染输入框控件,不需要点击编辑方式,直接就显示文本框
  • DSL查询文档
  • Android OpenSL ES 音频播放完整实现指南
  • AtCoder Beginner Contest 408
  • 电路笔记(元器件):并串转换芯片 SN65LV1023A 10:1 LVDS 串行器/解串器变送器 100 至 660Mbps
  • HarmonyOS开发:设备管理使用详解
  • shell脚本总结15:grep命令的使用方法
  • 不变性(Immutability)模式
  • 丝路幽径:穿梭于Linux多线程控制的秘境
  • 专题一_双指针_快乐数
  • LeetCode 3442.奇偶频次间的最大差值 I:计数
  • 使用分级同态加密防御梯度泄漏
  • Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:智驿AI系统(前后端源码 + 数据库 sql 脚本)
  • 实现多路视频截图预览之后上传到后台系统
  • 2025年ASOC SCI2区TOP,协同搜索框架自适应算法+多无人机巡检规划,深度解析+性能实测
  • 专题一_双指针_复写零
  • HDFS 3.4.1 集成Kerberos 实现账户认证
  • 驭码CodeRider 2.0深度测评:助力高效开发【探索化学奇妙世界】网站
  • 【靶场】xxe漏洞2