本文介绍在HCS ModelArts控制台基于MindSpeed-LLM框架进行Qwen3模型微调(全参/Lora)训练全过程。
[TOC]
本文基于MindSpeed-LLM框架对Qwen3-32B模型适配进行微调,MindSpeed开源社区地址:https://gitee.com/ascend/MindSpeed-LLM,主要分为以下几个部分。
注:本教程同样适用于Qwen3其他参数量模型,按需从MindSpeed-LLM中获取example训练脚本修改即可。
基于MindSpeed进行开源模型微调训练时,需根据MindSpeed要求的配套版本制作镜像并适配ModelArts。参考MindSpeed-LLM配置环境要求:https://gitee.com/ascend/MindSpeed-LLM/blob/2.1.0/docs/pytorch/install_guide.md,具体配置要求如下:
MindSpeed-LLM的主要依赖配套如下表,安装步骤参考安装指导。(以下仅供参考,请参照MindSpeed最新文档的环境要求准备环境)
使用约束
| 依赖软件 | 版本 |
|---|---|
| 昇腾NPU驱动 | >=25.0.RC1.1商发版本 |
| 昇腾NPU固件 | >=25.0.RC1.1商发版本 |
| CANN Toolkit | >=8.1.RC1商发版本 |
| CANN Kernel | >=8.1.RC1商发版本 |
| CANN NNAL | >=8.1.RC1商发版本 |
| Python | >=3.10 |
| PyTorch | >=2.1.0 |
| torch_npu插件 | >=2.1.0 |
| apex | 商发版本 |
| transformers | >=4.51.0(与模型配套,Qwen3要求4.51.0及以上版本) |
硬件设备
| 设备型号 | NPU配置 |
|---|---|
| Atlas 800I A2 910B | 16/32卡 |
准备配套Python源码包,根据需要下载对应版本,下载地址: https://www.python.org/downloads/。
使用./configure --prefix=/usr/local/python3 & make & make install命令安装Python。
下载CANN配套版本,根据需要下载对应版本,下载地址: https://www.hiascend.com/developer/download/community/result?module=cann&cann=8.2.RC1。
使用下列命令安装CANN toolkit、kernels、nnal:
chmod +x Ascend-cann-*.run
./$(ls -t Ascend-cann-toolkit*.run|head -n 1) --install --quiet
./$(ls -t Ascend-cann-kernels*.run|head -n 1) --install --quiet
source /usr/local/Ascend/ascend-toolkit/set_env.sh
./$(ls -t Ascend-cann-nnal*.run|head -n 1) --install --quiet
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh下载配套torch、torch-npu依赖包,根据需要下载对应版本,下载地址:https://www.hiascend.com/document/detail/zh/Pytorch/710/configandinstg/instg/insg_0004.html。
使用下列命令安装Torch&torch_npu:
pip install --upgrade pip
pip install $(ls -t /tmp/torch*.whl|grep -v "torch_npu"|head -n 1)
pip install $(ls -t /tmp/torch_npu*.whl|head -n 1)参照社区依赖安装MindSpeed-LLM,社区安装指导链接:https://gitee.com/ascend/MindSpeed-LLM/blob/2.1.0/docs/pytorch/install_guide.md
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
# 安装MindSpeed加速库
git clone https://gitee.com/ascend/MindSpeed.git
cd MindSpeed
git checkout 2c085cc9 # checkout commit from MindSpeed core_r0.8.0 in 2025.04.01
pip install -r requirements.txt
pip3 install -e .
cd ..
# 准备MindSpeed-LLM及Megatron-LM源码
git clone https://gitee.com/ascend/MindSpeed-LLM.git
# megatron从github下载,请确保网络能访问
git clone https://github.com/NVIDIA/Megatron-LM.git
cd Megatron-LM
git checkout core_r0.8.0
cp -r megatron ../MindSpeed-LLM/
cd ../MindSpeed-LLM
git checkout 2.1.0
pip install -r requirements.txt # 安装其余依赖库在ModelArts上运行的镜像需要进行ModelArts适配(参考https://support.huaweicloud.com/usermanual-standard-modelarts/docker-modelarts_0029.html) 添加用户组ma-group(gid:100)、用户ma-user(uid:1000),并设置/usr/local目录权限。
# add ma user group if not exists
groupadd ma-group -g 100
# add and chown ma user if not exists
useradd -m -d /home/ma-user -s /bin/bash -g 100 -u 1000 ma-user
# add permission
chown -R ma-user:100 /usr/local/*为简化上述镜像制作流程,本文提供基于OpenEuler基础镜像从零制作MindSpeed-LLM镜像
基于OpenEuler基础镜像,从零开始制作,根据上述环境配置要求制作MA训练镜像:(以下脚本在基于Arm64架构的Mac上制作镜像验证通过)。常用依赖直接使用ma-user安装,不需要重新适配MA,可以有效控制镜像体积。安装CANN部署参考CANN社区制作。
镜像制作步骤脚本及使用方法同上一节,不适配MA即可。
Docker一键构建脚本仅供参考,可按需修改配套版本,以使用不同模型。
ARG BASE_IMAGE=openeuler-22.03-lts-sp3:latest
FROM ${BASE_IMAGE}
# Install basic software
RUN yum update -y && \
yum install -y \
gcc \
gcc-c++ \
make \
cmake \
curl \
zlib-devel \
bzip2-devel \
openssl-devel \
ncurses-devel \
sqlite-devel \
readline-devel \
tk-devel \
gdbm-devel \
libpcap-devel \
xz-devel \
libev-devel \
expat-devel \
libffi-devel \
systemtap-sdt-devel \
unzip \
pciutils \
net-tools \
lapack-devel \
gcc-gfortran \
util-linux \
findutils \
wget \
ca-certificates \
bash \
glibc \
git \
patch \
&& yum clean all \
&& rm -rf /var/cache/yum \
&& rm -rf /tmp/*
# Install Python
ENV PATH=/usr/local/python3/bin:${PATH}
ADD ./Python-3* /tmp
RUN cd /tmp/Python-3* && \
mkdir -p /usr/local/python3/lib && \
./configure --enable-shared --enable-shared LDFLAGS="-Wl,-rpath /usr/local/python3/lib" --prefix=/usr/local/python3 && \
make -j $(nproc) && \
make altinstall && \
ln -sf $(ls -t /usr/local/python3/bin/python3.*[0-9]|head -n 1) /usr/local/python3/bin/python3 && \
ln -sf $(ls -t /usr/local/python3/bin/pip3.*[0-9]|head -n 1) /usr/local/python3/bin/pip3 && \
ln -sf /usr/local/python3/bin/python3 /usr/local/python3/bin/python && \
ln -sf /usr/local/python3/bin/pip3 /usr/local/python3/bin/pip && \
rm -rf /tmp/*
# Stage 2: Install CANN
# Note: Install CANN runtime dependencies
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && pip config set global.timeout 6000
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir \
attrs \
cython \
numpy \
decorator \
sympy \
cffi \
pyyaml \
pathlib2 \
psutil \
protobuf \
scipy \
requests \
absl-py
COPY ./Ascend-cann*.run /tmp/
RUN cd /tmp && if (ls Ascend-cann*.run 1>/dev/null 2>&1); then \
ls && chmod +x Ascend-cann-*.run \
&& ./$(ls -t Ascend-cann-toolkit*.run|head -n 1) --quiet --install --install-for-all \
&& ./$(ls -t Ascend-cann-kernels*.run|head -n 1) --quiet --install --install-for-all \
&& source /usr/local/Ascend/ascend-toolkit/set_env.sh \
&& ./$(ls -t Ascend-cann-nnal*.run|head -n 1) --quiet --install --install-for-all \
&& source /usr/local/Ascend/ascend-toolkit/set_env.sh \
&& source /usr/local/Ascend/nnal/atb/set_env.sh; \
else \
echo "CANN install package does not exist, skip."; \
fi \
&& rm -f /tmp/Ascend-cann*.run
# Note: Toolkit Environment variables, obtained from /usr/local/Ascend/ascend-toolkit/set_env.sh
ENV ASCEND_TOOLKIT_HOME=/usr/local/Ascend/ascend-toolkit/latest
ENV LD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/common/:/usr/local/Ascend/driver/lib64/driver/:$LD_LIBRARY_PATH
ENV LD_LIBRARY_PATH=${ASCEND_TOOLKIT_HOME}/lib64:${ASCEND_TOOLKIT_HOME}/lib64/plugin/opskernel:${ASCEND_TOOLKIT_HOME}/lib64/plugin/nnengine:${ASCEND_TOOLKIT_HOME}/opp/built-in/op_impl/ai_core/tbe/op_tiling:$LD_LIBRARY_PATH
ENV LD_LIBRARY_PATH=${ASCEND_TOOLKIT_HOME}/tools/aml/lib64:${ASCEND_TOOLKIT_HOME}/tools/aml/lib64/plugin:$LD_LIBRARY_PATH
ENV PYTHONPATH=${ASCEND_TOOLKIT_HOME}/python/site-packages:${ASCEND_TOOLKIT_HOME}/opp/built-in/op_impl/ai_core/tbe:$PYTHONPATH
ENV PATH=${ASCEND_TOOLKIT_HOME}/bin:${ASCEND_TOOLKIT_HOME}/compiler/ccec_compiler/bin:${ASCEND_TOOLKIT_HOME}/tools/ccec_compiler/bin:$PATH
ENV ASCEND_AICPU_PATH=${ASCEND_TOOLKIT_HOME}
ENV ASCEND_OPP_PATH=${ASCEND_TOOLKIT_HOME}/opp
ENV TOOLCHAIN_HOME=${ASCEND_TOOLKIT_HOME}/toolkit
ENV ASCEND_HOME_PATH=${ASCEND_TOOLKIT_HOME}
# Note: NNAL Environment variables, obtained from /usr/local/Ascend/nnal/set_env.sh
ENV ATB_HOME_PATH=/usr/local/Ascend/nnal/atb/latest/atb/cxx_abi_0
ENV LD_LIBRARY_PATH=${ATB_HOME_PATH}/lib:${ATB_HOME_PATH}/examples:${ATB_HOME_PATH}/tests/atbopstest:${LD_LIBRARY_PATH}
ENV PATH=${ATB_HOME_PATH}/bin:$PATH
ENV ATB_STREAM_SYNC_EVERY_KERNEL_ENABLE=0
ENV ATB_STREAM_SYNC_EVERY_RUNNER_ENABLE=0
ENV ATB_STREAM_SYNC_EVERY_OPERATION_ENABLE=0
ENV ATB_OPSRUNNER_SETUP_CACHE_ENABLE=1
ENV ATB_OPSRUNNER_KERNEL_CACHE_LOCAL_COUNT=1
ENV ATB_OPSRUNNER_KERNEL_CACHE_GLOABL_COUNT=5
ENV ATB_WORKSPACE_MEM_ALLOC_ALG_TYPE=1
ENV ATB_WORKSPACE_MEM_ALLOC_GLOBAL=0
ENV ATB_COMPARE_TILING_EVERY_KERNEL=0
ENV ATB_HOST_TILING_BUFFER_BLOCK_NUM=128
ENV ATB_DEVICE_TILING_BUFFER_BLOCK_NUM=32
ENV ATB_SHARE_MEMORY_NAME_SUFFIX=""
ENV ATB_MATMUL_SHUFFLE_K_ENABLE=1
ENV ASDOPS_LOG_LEVEL=ERROR
ENV ASDOPS_LOG_TO_STDOUT=0
ENV ASDOPS_LOG_TO_FILE=1
ENV ASDOPS_LOG_TO_FILE_FLUSH=0
ENV ASDOPS_LOG_TO_BOOST_TYPE=atb
ENV ASDOPS_LOG_PATH=/root
ENV LCCL_DETERMINISTIC=0
ENV LCCL_PARALLEL=0
ENV PYTHONUNBUFFERED=1
SHELL [ "/bin/bash", "-c" ]
# Note: Set environment variables
RUN CANN_TOOLKIT_ENV_FILE="/usr/local/Ascend/ascend-toolkit/set_env.sh" && \
CANN_NNAL_ENV_FILE="/usr/local/Ascend/nnal/atb/set_env.sh" && \
echo "source ${CANN_TOOLKIT_ENV_FILE}" >> /etc/profile && \
echo "source ${CANN_TOOLKIT_ENV_FILE}" >> ~/.bashrc && \
echo "source ${CANN_NNAL_ENV_FILE}" >> /etc/profile && \
echo "source ${CANN_NNAL_ENV_FILE}" >> ~/.bashrc
# 3. install torth & torth_npu
COPY ./torch*.whl /tmp/
RUN pip install --upgrade pip \
&& pip install $(ls -t /tmp/torch*.whl|grep -v "torch_npu"|head -n 1) \
&& pip install $(ls -t /tmp/torch_npu*.whl|head -n 1)
# 4. 适配MA
RUN useradd -m -d /home/ma-user -s /bin/bash -g 100 -u 1000 ma-user
USER ma-user
WORKDIR /home/ma-user
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && pip config set global.timeout 6000
# RUN git config --global --unset http.proxy && git config --global --unset https.proxy
# 4. install Megatron-LM & MindSpeed & MindSpeed LLM
RUN cd ~ \
&& git clone https://github.com/NVIDIA/Megatron-LM.git \
&& git clone https://gitee.com/ascend/MindSpeed.git \
&& git clone https://gitee.com/ascend/MindSpeed-LLM.git
ARG MEGATRON_LM_TAG=core_r0.8.0
ARG MINDSPEED_TAG=2c085cc9
ARG MINDSPEED_LLM_TAG=2.1.0
RUN cd ~ && cd Megatron-LM && git checkout ${MEGATRON_LM_TAG} && cp -r megatron ../MindSpeed-LLM/ \
&& cd ../MindSpeed && git checkout ${MINDSPEED_TAG} && pip install -r requirements.txt && pip install -e . \
&& cd ../MindSpeed-LLM && git checkout ${MINDSPEED_LLM_TAG} && pip install -r requirements.txt
# 5. install transformer
ARG TRANSFORMERS_VERSION=
RUN if [ -n "$TRANSFORMERS_VERSION" ]; then echo "transformers is ${TRANSFORMERS_VERSION}" && pip install transformers==${TRANSFORMERS_VERSION}; else echo "transformers version is empty, skip"; fi
# 6. install apex
ARG APEX_TAG=master
RUN cd ~ && git clone https://gitee.com/ascend/apex.git \
&& export TORCH_DEVICE_BACKEND_AUTOLOAD=0 \
&& cd apex && git checkout ${APEX_TAG} && bash scripts/build.sh --python=$(python3 -V|awk '{print $2}'|cut -d. -f1,2) && cd apex/dist \
&& pip uninstall apex && pip install --upgrade $(ls -t apex*.whl|head -n 1) \
&& unset TORCH_DEVICE_BACKEND_AUTOLOAD(1)准备配套Python源码包,根据需要下载对应版本,并放到与build_mindspeeed_image.sh相同的目录下,下载地址: https://www.python.org/downloads/
(2)下载CANN配套版本(仅支持run后缀文件),并放到与build_mindspeeed_image.sh相同的目录下,下载地址: https://www.hiascend.com/developer/download/community/result?module=cann&cann=8.2.RC1。
(3)下载配套torch、torch-npu依赖包,并放到与build_mindspeeed_image.sh相同的目录下,下载地址:https://www.hiascend.com/document/detail/zh/Pytorch/710/configandinstg/instg/insg_0004.html;文件夹结构如下图所示,脚本会自动识别Python、torch及torch-npu安装包。
(4)通过bash执行一键构建脚本,脚本参数为构建镜像的tag:
文件存放目录参考下图:

bash build_mindspeeed_image.sh mindspeed:2025.rc1-arm_qwen3_for_ma
脚本需要依赖参数,参数说明如下:
Please enter the base image of MindSpeed:
Please enter the tag or branch of Megatron-LM.git: (default: core_r0.8.0): 模型依赖Megatron-LM分支或者tag
Please enter the tag or branch of MindSpeed.git: (default: 2c085cc9): 模型依赖昇腾MindSpeed release分支或者tag
Please enter the tag or branch of MindSpeed-LLM.git: (default: 2.1.0): 模型依赖昇腾MindSpeed-LLM release分支或者tag
Please enter the version of transformers(nullable, skip when empty): 模型依赖transformers版本号,不设置跳过更新transformers
Please enter the tag or branch of apex.git: (default: master): 模型依赖昇腾apex release分支或者tag(5)根据提示完成构建即可
镜像制作完成后上传至SWR中。脚本归档参见: https://ai.gitcode.com/Ascend-SACT/Qwen3-32B/blob/main/build_mindspeeed_image.sh
将mindspeed-llm:${version}上传到SWR仓库。
创建一台ecs服务器/或者找到一台可以连通SWR的linux服务器,需要安装docker环境
上传镜像文件mindspeed-llm_${version}.tar到linux服务器,并登录机器执行 docker load -i mindspeed-llm:${version}.tar
镜像打标签,和swr上的仓库地址和组织名保持一致docker tag mindspeed-llm:${version} <镜像仓库地址>/<swr组织名>/mindspeed-llm:${version}
获取swr登录信息
进入HCS环境,选择SWR服务,点击总览页下的 登录“登录指令” 按钮获取SWR临时登录指令:docker login xxxxxxxxx
推送镜像至SWR仓库
获取上一步的镜像tag信息,执行如下命令将镜像推送至SWR仓库: docker push <镜像仓库地址>/<swr组织名>/mindspeed-llm:${version}
权重可以从魔乐、魔塔社区及huggingface等途径获取需要的开源镜像。
魔乐社区Qwen3-32B下载地址:https://www.modelscope.cn/models/Qwen/Qwen3-32B/files
使用OBSUtil上传模型权重至OBS:
创建一台ecs服务器/或者找到一台可以连通OBS的Linux服务器 从HCS环境OBS下载OBSUtil安装包并上传到Linux服务 解压OBSUtil并copy到/usr/local/bin
tar -xvf obsutil_xxx.tar.gz
cp -f obsutil_xxx/obsutil /usr/local/bin/登录OBS并上传文件至OBS
obsutil config -i=<ak> -k=<sk> -e=<endpoint>
obsutil cp -r -f <local_weight_path> <obs_weight_path>训练数据由行内老师提供,本文仅提供训练方法,以开源数据集alpaca为例,进行训练过程验证。alpaca训练数据集:https://huggingface.co/datasets/tatsu-lab/alpaca/,下载后使用OBSUtil上传至OBS。
obsutil cp -r -f <local_data_path> <obs_data_path>训练任务分为数据预处理、huggingface权重转换为mcore、启动训练及mcore权重转换回huggingface四个阶段。本文基于MindSpeed适配example脚本修改,下载对应模型权重训练脚本https://gitee.com/ascend/MindSpeed-LLM/tree/2.1.0/examples/mcore,具体参数可参考MindSpeed-LLM文档。
按照训练要求进行修改,修改过程如下,仅作参考。修改完之后上传至OBS。
obsutil cp -r -f <local_script_path> <obs_script_path># set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
cd ~/MindSpeed-LLM/
# copy train origin data to dataset
cp $DATA_PATH/* ~/MindSpeed-LLM/dataset/
mkdir ./finetune_dataset
python ./preprocess_data.py \
--input ./dataset \
--tokenizer-name-or-path /home/mind/model/Qwen3-32B/ \
--output-prefix ./finetune_dataset/alpaca \
--handler-name AlpacaStyleInstructionHandler \
--tokenizer-type PretrainedFromHF \
--workers 16 \
--log-interval 1000 \
--prompt-type qwen注:
参数说明
| 参数 | 说明 | 必填 |
|---|---|---|
--input | 支持输入数据集目录或文件,目录则处理全部文件, 支持.parquet、.csv、.json、.jsonl、.txt、.arrow格式,同一目录要求数据格式保持一致 | ✅ |
--tokenizer-type | 说明使用tokenizer类别,参数值为PretrainedFromHF时,词表路径填写模型目录即可 | ✅ |
--tokenizer-name-or-path | 配合tokenizer-type,目标模型的tokenizer原数据文件夹,用于数据集的转换 | |
--tokenizer-model | 配合指定分词器模型的路径,路径具体到tokenizer.model文件 | |
--output-prefix | 转换后输出的数据集文件的文件名前缀 | ✅ |
--workers | 多进程数据集处理 | ✅ |
# set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
cd ~/MindSpeed-LLM/
mkdir -p $OUTPUT_PATH/qwen3_mcore
python convert_ckpt.py \
--use-mcore-models \
--model-type GPT \
--load-model-type hf \
--save-model-type mg \
--target-tensor-parallel-size 4 \
--target-pipeline-parallel-size 4 \
--spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
--load-dir /home/mind/model/Qwen3-32B/ \
--save-dir $OUTPUT_PATH/qwen3_mcore/ \
--tokenizer-model /home/mind/model/Qwen3-32B/tokenizer.json \
--model-type-hf qwen3 \
--params-dtype bf16注:
| 参数 | 说明 | 必填 |
|---|---|---|
--model-type GPT | 指定模型类型为GPT系列 | ✅ |
--use-mcore-models | 转换为Megatron-Mcore格式 | ✅ |
--target-tensor-parallel-size 1 | 张量并行度设置(建议配置1) | ✅ |
--target-pipeline-parallel-size 4 | 流水线并行度设置(建议保持4) | ✅ |
--tokenizer-model | 指定分词器路径 | ✅ |
--load-model-type | 加载权重的类别(可以是hf、mg) | ✅ |
--save-model-type | 存储权重的类别(可以是hf、mg) | ✅ |
--load-dir | 权重文件加载路径 | ✅ |
--save-dir | 权重文件保存路径 | ✅ |
--model-type-hf | huggingface模型类别,默认为llama2 | |
--params-dtype | 指定权重转换后的权重精度模式,默认为fp16,如果源文件格式为bf16,则需要设置为bf16 | ✅ |
这里TP/PP并行需要跟实际训练使用的卡数对应,这里以A2双机16卡为例。
ModelArts在启动容器时注入相关多机环境变量,可以直接使用MA中的环境变量来进行MindSpeed多机配置,避免人为修改脚本容器IP,设置主节点等操作,提升训练便捷程度。
注:多机配置解析解读 ModelArts环境变量:
| 环境变量 | 说明 |
|---|---|
| VC_WORKER_HOSTS | 环境变量由ModelArts注入,包含所有worker节点hostname,以英文逗号分隔。这个统一取第一个节点为MASTER节点 |
| MA_NUM_HOSTS | 环境变量由ModelArts注入,为训练节点数 |
| VC_TASK_INDEX | 环境变量由ModelArts注入,为Worker节点序号 |
| MA_NUM_GPUS | 环境变量由ModelArts注入,为每个节点卡数 |
MindSpeed-LLM多机配置:
# Change for multinode config
NPUS_PER_NODE="$MA_NUM_GPUS" # 读取ModelArts下发的卡数
MASTER_ADDR="${VC_WORKER_HOSTS%%,*}" # 设置MASTER节点HOST
MASTER_PORT=6000
NNODES="$MA_NUM_HOSTS" # 设置训练节点数
NODE_RANK="$VC_TASK_INDEX" # 分配的节点索引
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) # 计算总卡数创建全参微调训练任务脚本,修改多机训练脚本tune_qwen3_32b_4K_full_ptd.sh,多机推理可参考本脚本指定主节点IP、节点序号、节点数等信息,直接与ModelArts页面选择资源对接,无需手动修改:
#!/bin/bash
export CUDA_DEVICE_MAX_CONNECTIONS=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
cd ~/MindSpeed-LLM/
mkdir -p $OUTPUT_PATH/ckpt
# Change for multinode config
# 读取ModelArts下发的卡数
NPUS_PER_NODE="$MA_NUM_GPUS"
# 设置MASTER节点HOST
MASTER_ADDR="${VC_WORKER_HOSTS%%,*}"
MASTER_PORT=6000
# 设置MA下发的节点数
NNODES="$MA_NUM_HOSTS"
# 设置MA分配的节点索引
NODE_RANK="$VC_TASK_INDEX"
# 计算总卡数
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))
# please fill these path configurations
CKPT_LOAD_DIR="$OUTPUT_PATH/qwen3_mcore/"
CKPT_SAVE_DIR="$OUTPUT_PATH/ckpt/"
DATA_PATH="./finetune_dataset/alpaca "
TOKENIZER_PATH="/home/mind/model/Qwen3-32B"
# TP\PP\MBS\GBS\SEQ_LENGTH\TRAIN_ITERS 按照需求设置
TP=4
PP=4
MBS=2
GBS=16
SEQ_LENGTH=4096
TRAIN_ITERS=2000
DISTRIBUTED_ARGS="
--nproc_per_node $NPUS_PER_NODE \
--nnodes $NNODES \
--node_rank $NODE_RANK \
--master_addr $MASTER_ADDR \
--master_port $MASTER_PORT
"
OPTIMIZE_ARGS="
--use-flash-attn \
--use-fused-rotary-pos-emb \
--use-rotary-position-embeddings \
--use-fused-swiglu \
--use-fused-rmsnorm \
--no-masked-softmax-fusion \
--use-distributed-optimizer
"
TRAIN_ARGS="
--micro-batch-size ${MBS} \
--global-batch-size ${GBS} \
--lr 1.25e-6 \
--lr-decay-style cosine \
--min-lr 1.25e-7 \
--weight-decay 1e-1 \
--lr-warmup-fraction 0.01 \
--attention-dropout 0.0 \
--init-method-std 0.01 \
--hidden-dropout 0.0 \
--clip-grad 1.0 \
--adam-beta1 0.9 \
--adam-beta2 0.95 \
--initial-loss-scale 4096 \
--seed 42 \
--bf16 \
--train-iters ${TRAIN_ITERS} \
--seq-length ${SEQ_LENGTH} \
--no-shared-storage
"
MODEL_PARALLEL_ARGS="
--tensor-model-parallel-size ${TP} \
--pipeline-model-parallel-size ${PP}
"
GPT_ARGS="
--use-mcore-models \
--spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
--kv-channels 128 \
--qk-layernorm \
--tokenizer-name-or-path ${TOKENIZER_PATH} \
--max-position-embeddings ${SEQ_LENGTH} \
--num-layers 64 \
--hidden-size 5120 \
--ffn-hidden-size 25600 \
--num-attention-heads 64 \
--tokenizer-type PretrainedFromHF \
--make-vocab-size-divisible-by 1 \
--padded-vocab-size 151936 \
--rotary-base 1000000 \
--untie-embeddings-and-output-weights \
--disable-bias-linear \
--position-embedding-type rope \
--normalization RMSNorm \
--swiglu \
--attention-softmax-in-fp32 \
--no-gradient-accumulation-fusion \
--group-query-attention \
--num-query-groups 8
"
DATA_ARGS="
--data-path $DATA_PATH \
--split 100,0,0
"
OUTPUT_ARGS="
--load ${CKPT_LOAD_DIR} \
--save ${CKPT_SAVE_DIR} \
--log-interval 1 \
--save-interval ${TRAIN_ITERS} \
--eval-interval ${TRAIN_ITERS} \
--eval-iters 0 \
--no-load-optim \
--no-load-rng
"
TUNE_ARGS="
--finetune \
--stage sft \
--is-instruction-dataset \
--tokenizer-not-use-fast \
--prompt-type qwen \
--variable-seq-lengths
"
torchrun $DISTRIBUTED_ARGS posttrain_gpt.py \
$GPT_ARGS \
$DATA_ARGS \
$OUTPUT_ARGS \
$OPTIMIZE_ARGS \
$TRAIN_ARGS \
$TUNE_ARGS \
$MODEL_PARALLEL_ARGS \
--distributed-backend nccl \
| tee logs/tune_qwen3_32b_full_ptd.log以上脚本训练调优配置按需修改,本文不涉及训练参数调优过程。
创建Lora微调训练任务脚本,修改多机训练脚本tune_qwen3_32b_4K_lora_ptd.sh,多机推理可参考本脚本指定主节点IP,节点序号,节点数等信息,直接与ModelArts页面选择资源对接,无需手动修改:
#!/bin/bash
export CUDA_DEVICE_MAX_CONNECTIONS=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
cd ~/MindSpeed-LLM/
mkdir -p $OUTPUT_PATH/ckpt
export HCCL_CONNECT_TIMEOUT=1800
# Change for multinode config
# 读取ModelArts下发的卡数
NPUS_PER_NODE="$MA_NUM_GPUS"
# 设置MA节点HOST
MASTER_ADDR="${VC_WORKER_HOSTS%%,*}"
MASTER_PORT=6014
# 设置MA下发的节点数
NNODES="$MA_NUM_HOSTS"
# 设置MA分配的节点索引
NODE_RANK="$VC_TASK_INDEX"
# 计算总卡数
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))
# please fill these path configurations
CKPT_LOAD_DIR="$OUTPUT_PATH/qwen3_mcore/"
CKPT_SAVE_DIR="$OUTPUT_PATH/ckpt/"
DATA_PATH="./finetune_dataset/alpaca "
TOKENIZER_PATH="/home/mind/model/Qwen3-32B"
TP=4
PP=4
SEQ_LENGTH=4096
TRAIN_ITERS=2000
DISTRIBUTED_ARGS="
--nproc_per_node $NPUS_PER_NODE \
--nnodes $NNODES \
--node_rank $NODE_RANK \
--master_addr $MASTER_ADDR \
--master_port $MASTER_PORT
"
OPTIMIZE_ARGS="
--use-flash-attn \
--use-fused-rotary-pos-emb \
--use-rotary-position-embeddings \
--use-fused-swiglu \
--use-fused-rmsnorm \
--no-masked-softmax-fusion \
--use-distributed-optimizer
"
TRAIN_ARGS="
--micro-batch-size 4 \
--global-batch-size 16 \
--lr 1.25e-5 \
--lr-decay-style cosine \
--min-lr 1.25e-7 \
--weight-decay 1e-1 \
--lr-warmup-fraction 0.01 \
--attention-dropout 0.0 \
--init-method-std 0.01 \
--hidden-dropout 0.0 \
--clip-grad 1.0 \
--adam-beta1 0.9 \
--adam-beta2 0.95 \
--initial-loss-scale 4096 \
--seed 42 \
--bf16 \
--train-iters ${TRAIN_ITERS} \
--seq-length ${SEQ_LENGTH} \
--no-shared-storage
"
MODEL_PARALLEL_ARGS="
--tensor-model-parallel-size ${TP} \
--pipeline-model-parallel-size ${PP}
"
GPT_ARGS="
--use-mcore-models \
--spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
--kv-channels 128 \
--qk-layernorm \
--tokenizer-name-or-path ${TOKENIZER_PATH} \
--max-position-embeddings ${SEQ_LENGTH} \
--num-layers 64 \
--hidden-size 5120 \
--ffn-hidden-size 25600 \
--num-attention-heads 64 \
--tokenizer-type PretrainedFromHF \
--make-vocab-size-divisible-by 1 \
--padded-vocab-size 151936 \
--rotary-base 1000000 \
--untie-embeddings-and-output-weights \
--disable-bias-linear \
--position-embedding-type rope \
--normalization RMSNorm \
--swiglu \
--attention-softmax-in-fp32 \
--no-gradient-accumulation-fusion \
--group-query-attention \
--num-query-groups 8
"
DATA_ARGS="
--data-path $DATA_PATH \
--split 100,0,0
"
OUTPUT_ARGS="
--load ${CKPT_LOAD_DIR} \
--save ${CKPT_SAVE_DIR} \
--log-interval 1 \
--save-interval ${TRAIN_ITERS} \
--eval-interval ${TRAIN_ITERS} \
--eval-iters 0 \
--no-load-optim \
--no-load-rng
"
TUNE_ARGS="
--finetune \
--stage sft \
--is-instruction-dataset \
--tokenizer-not-use-fast \
--prompt-type qwen \
--variable-seq-lengths \
--lora-r 16 \
--lora-alpha 32 \
--lora-fusion \
--lora-target-modules linear_qkv linear_proj linear_fc1 linear_fc2
"
torchrun $DISTRIBUTED_ARGS posttrain_gpt.py \
$GPT_ARGS \
$DATA_ARGS \
$OUTPUT_ARGS \
$OPTIMIZE_ARGS \
$TRAIN_ARGS \
$TUNE_ARGS \
$MODEL_PARALLEL_ARGS \
--distributed-backend nccl \
| tee logs/tune_qwen3_32b_lora_ptd.log以上脚本训练调优配置按需修改,本文不涉及训练参数调优过程。
全参微调权重转换脚本:ckpt_convert_qwen3_mcore2hf.sh
# set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
# master节点进行最后的权重转换
if [[ "$VC_TASK_INDEX" == 0 ]]; then
# 汇总权重到OBS挂载路径,需要自行汇总
echo "This is master, doing mcore to hf"
# 汇总所有节点权重,OBS地址可以从MA_OUTPUTS环境变量中获取romote,主要需要登录,todo:可以使用moxing解决,目前已跟产品线沟通发布外部商发版本
obsutil cp -r -f obs://qwen3/llmd/ckpt/ $OUTPUT_PATH/
mkdir -p $OUTPUT_PATH/qwen3_hf
# 这个转换需要目录下有原始权重,cp到output下
cp -rf /home/mind/model/Qwen3-32B/* $OUTPUT_PATH/qwen3_hf
python convert_ckpt.py \
--use-mcore-models \
--model-type GPT \
--load-model-type mg \
--save-model-type hf \
--target-tensor-parallel-size 1 \
--target-pipeline-parallel-size 1 \
--spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
--load-dir $OUTPUT_PATH/ckpt/ \
--save-dir $OUTPUT_PATH/qwen3_hf/ \
--model-type-hf qwen3 \
--params-dtype bf16
else
echo "This is slave, ignore mcore to hf"
fi将准备好的脚本上传至OBS。
Lora权重转换脚本:ckpt_convert_qwen3_mcore2hf_lora.sh
# 修改 ascend-toolkit 路径
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH
if [[ "$VC_TASK_INDEX" == 0 ]]; then
# 汇总权重到OBS挂载路径,需要自行汇总
echo "This is master, doing mcore to hf"
# 汇总所有节点权重,OBS地址可以从MA_OUTPUTS环境变量中获取romote,主要需要登录,todo:可以使用moxing解决,目前已跟产品线沟通发布外部商发版本
obsutil cp -r -f obs://qwen3/llmd/ckpt/ $OUTPUT_PATH/
mkdir -p $OUTPUT_PATH/qwen3_hf
# 这个转换需要目录下有原始权重
cp -rf /home/mind/model/Qwen3-32B/* $OUTPUT_PATH/qwen3_hf
python convert_ckpt.py \
--use-mcore-models \
--model-type GPT \
--load-model-type mg \
--save-model-type hf \
--target-tensor-parallel-size 1 \
--target-pipeline-parallel-size 1 \
--spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
--lora-r 16 \
--lora-alpha 32 \
--lora-target-modules linear_qkv linear_proj linear_fc1 linear_fc2 \
--load-dir $OUTPUT_PATH/qwen3_mcore/ \
--lora-load $OUTPUT_PATH/ckpt/ \
--save-dir $OUTPUT_PATH/qwen3_hf/ \
--model-type-hf qwen3 \
fi如需单独转换Lora权重,添加如下参数:
| 参数 | 说明 | 可选/必选 |
|---|---|---|
| --save-lora-to-hf | lora转hf时设置此参数以指定仅转换lora权重 | 可选 |
| --load-checkpoint-loosely | 允许松弛加载,转换lora权重时,需要设置此参数 | 可选 |
输入训练任务“名称”

创建方式选择”自定义算法”
启动方式选择“自定义”
镜像选择 “步骤一制作训练镜像上传至SWR的镜像”
代码目录选择“步骤二上传的权重目录”
启动命令输入:
bash $SCRIPT_PATH/data_convert_qwen3_32b_instruction.sh \
&& bash $SCRIPT_PATH/ckpt_convert_qwen3_32b_hf2mcore.sh \
&& bash $SCRIPT_PATH/tune_qwen3_32b_4K_full_ptd.sh \
&& sleep 1000 && bash $SCRIPT_PATH/ckpt_convert_qwen3_mcore2hf.sh
在“输入”中添加变量SCRIPT_PATH,数据存储位置选择步骤4中上传OBS的脚本路径,获取方式选择环境变量。
在“输入”中添加变量DATA_PATH,数据存储位置选择步骤3中上传OBS的训练数据集路径,获取方式选择环境变量。
根据训练要求按需添加其他环境变量及超参等输入。
在“输出”中添加变量OUTPUT_PATH,数据存储位置训练完需要保存至OBS的路径,获取方式选择环境变量。
根据训练要求按需添加其他环境变量及超参等输出。
根据训练要求按需添加“超参”及“环境变量”。

选择训练需要的“专属资源池”,规格,计算节点个数等。

点击“创建”任务开始执行模型训练,当看到迭代信息时说明任务开始正常训练,可以关注loss曲线查看训练情况,等待模型训练完成。
注:调试脚本过程中可以选择调试模式,待脚本运行正常后可以创建生成模式正式开始训练。
以上截图来自公有云环境,页面略有区别。
可参考MindIE部署文档,注意训练转换完的权重不包含vocab.json、tokenizer.json、tokenizer_config.json等配置,需要手动拷贝。
https://gitee.com/ascend/MindSpeed-LLM/blob/master/docs/quick_start.md
答:经定位未source相应环境变量及PATH未添加driver路径,解决方案如下:
在脚本中添加如下代码,初始化环境:
# set_env
source /usr/local/Ascend/driver/bin/setenv.bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/set_env.sh
export LD_LIBARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBARY_PATH答:经查看代码、比对环境等操作后,最终定位到问题原因是镜像中的torch及torch-npu小版本存在错误,未使用官方适配推荐的版本。更换镜像后,问题得以解决。因此,在制作镜像时务必按照官方指导进行配置,以避免此类问题的发生。