IDD-2504.2

华为云NPU的使用方法&&多卡测试

1.额度转代金券

登录帐号以后点击链接:https://developer.huawei.com/home/center/incentive/my-quota

账号ID查询方式,在需要代金券的账号悬浮在华为ID上获得华为账号ID,具体参考微信里的资料。

2.1配置环境(1)模型训练入口(暂时无法启动CUDA,方法(2)可用)

经过测试,使用预置框架没法调整启动参数,必须要做一个镜像来启动。

/images/image-20250718145830805

最简单的方法是使用上方的notebook:

/images/image-20250718150114995

选择需要的基础预置框架:

/images/image-20250718150154646

这里直接用cpu启动,把requirements.txt拖到左侧的文件栏,启动终端

pip install -r requirements.txt

安装完成之后即可返回notebook主页点击保存当前的框架,这里跟着步骤走即可。

保存需要一定的时间大概10分钟,再次打开模型训练的训练作业,即可看到刚刚保存好的环境:

/images/image-20250718150048453

cd ${MA_WORKING_DIR}
python pretrain.py

2.2配置环境(2) Notebook入口(NPU最大64GB*8显存)

Notebook其实也和上面的(1)存在同样的问题,于是转向NPU来尝试,在这里发现https://developer.huaweicloud.com/develop/aigallery/article/detail?id=7860d972-247f-4d4a-af65-7f0f22b678c5有torch==2.1.0配NPU的镜像,所以需要把位置切换到华东二,华东二只提供Ascend NPU。

该配置方法比(1)更简单,因为就和普通notebook一样,不过需要通过OBS存储桶传递100MB以上的文件。

1.配置原始镜像

注册镜像

/images/image-20250721193105032

配置好之后注册,就会在列表中出现该镜像:

/images/image-20250721193151225

在创建notebook里选择该镜像,这里图片是我配置好环境保存的新镜像。

/images/image-20250721193037499

3.配置存储桶

搜索OBS对象存储服务

/images/image-20250718150958196

创建一个桶,然后把需要运行的文件存在这里即可。

由于每次限制上传100个文件,Symtime有500个文件左右,所以需要下载OBS Browser+:https://support.huaweicloud.com/browsertg-obs/obs_03_1003.html

根据https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html教程获取登录密钥。

使用AK方式登录即可。

一次上传最大500个文件。这里配置好的文件地址会在创建训练目录时选择:

/images/image-20250718151530574

4.1 启动运行训练模型

这里启动命令经过测试使用绝对地址会报错,所以直接用最简单的相对地址。

在model_interface.py里,不知道因为什么原因,这里的self.model_type会变成一串绝对地址出现报错No such file or directory,需要对文件修改:

/images/image-20250718150720176

修改这个变量为字符串和文件里的Symtime_base.yaml对应即可正常运行。

正常能跑的情况下出现一个没遇到过的警告问题:

DistilBertSdpaAttention is used but torch.nn.functional.scaled_dot_product_attention does not support output_attentions=True or head_mask. Falling back to the manual attention implementation, but specifying the manual implementation will be required from Transformers version v5.0.0 onwards. This warning can be removed using the argument attn_implementation="eager" when loading the model.

4.启动运行Notebook

/images/image-20250721194336024

由于内置的镜像为Python3.9所以要把这行改成:

def load_optimizer(self, parameters: Optional[Union[Tensor, List]]) -> Optimizer:

在导入部分:

from typing import Optional, List, Union

如果加载好的是配置好的镜像,假设你的文件名是Symtime-NPU,那么:

unzip Symtime-NPU
cd Symtime-NPU
python pretrain.py

如果是从新镜像开始那么先配置pip。

5.监控

/images/image-20250718151701859

将这里的系统日志取消勾选,看到的就是一般的训练日志。

/images/image-20250718151743779

监控界面不知道为什么GPU占用始终为0,难道说没有启用GPU?但是训练程序运行没有其他异常。

经过测试发现,华为虽然标的是cu12.1,但是在环境里的镜像是cuda11.4,这导致没有启动GPU:

/images/image-20250721133940026

5.1 监控notebook

右边是使用率,其他就是一个linux虚拟机。

由于没有跑满内存,所以继续尝试了:

python pretrain.py --batch_size 32

/images/image-20250721195159455

提高了batch_size之后占用率可以拉上来了。

多卡测试

官方链接:https://www.hiascend.com/document/detail/zh/Pytorch/60RC2/ptmoddevg/trainingmigrguide/PT_LMTMOG_0084.html?sub_id=%2Fzh%2FPytorch%2F60RC2%2Fptmoddevg%2Ftrainingmigrguide%2FPT_LMTMOG_0080.html

跟着官方demo走了一遍,发现HBM没有变化,于是调整了网络参数:

class NeuralNetwork(nn.Module): 
    def __init__(self): 
        super().__init__() 
        self.flatten = nn.Flatten() 
        self.linear_relu_stack = nn.Sequential(
        nn.Linear(28*28, 8192),
        nn.ReLU(),
        nn.Linear(8192, 8192),
        nn.ReLU(),
        nn.Linear(8192, 10)
    )

终于可以看到调用NPU的效果:

/images/image-20250723232714601

基本概念:

概念 说明
world_size 总进程数 = 总设备数(如8卡就是8)
rank 当前进程的唯一编号(0~world_size-1)
local_rank 当前进程在当前机器上的编号(0~设备数-1)
backend 通信后端,如hccl(华为 NPU 特有)
init_method/env 初始化进程组所使用的方式,env://最常见

适配Symtime的DDP

原始代码采用accelerate对GPU设备进行管理,而在华为的官方的手册里,需要采用DDP的方式来指定model的device。

经过测试,使用自动迁移不会启用多卡,所以这里需要手动迁移。

 model = DDP(model, device_ids=[local_rank_idx])

难点在于如何迁移acclerate并实现和单卡一致的效果。

原始代码通过accelerate实现设备自动管理:

self.accelerator.print(
                    Fore.RED + "Now is loading pretraining data" + Style.RESET_ALL,
                    end=" -> ",
                )
                train_loader = self.data_interface.get_dataloader()
                train_loader = self.accelerator.prepare_data_loader(
                    train_loader, device_placement=True
                )
                sleep(2)
                self.accelerator.print(
                    Fore.GREEN + "successfully loaded!" + Style.RESET_ALL
                )
                self.model.train()
                data_loader = tqdm(train_loader, file=sys.stdout)
                for step, (time, time_mask, sym_ids, sym_mask) in enumerate(
                    data_loader, 1
                ):
                    self.optimizer.zero_grad()
                    num_samples += time.shape[0]
                    # 直接在模型正向传播的过程中获得损失
                    loss_mtm, loss_mlm, loss_t2s, loss_s2t = self.model(
                        time, time_mask, sym_ids, sym_mask
                    )
                    # 获取和整合误差
                    loss = loss_mtm + loss_mlm + (loss_t2s + loss_s2t) / 2
                    # 误差的反向传播
                    self.accelerator.backward(loss)

如何把acclerate迁移到华为官方的DDP?

官方实现:

def train(args):
    """训练函数"""
    world_size = int(os.environ["WORLD_SIZE"])  # 获取分布式训练的进程数
    local_rank_idx = int(os.environ["LOCAL_RANK"])  # 获取本地进程索引

    devices_per_node = torch.npu.device_count()  # 获取每个节点的 NPU 设备数量

    dist.init_process_group("hccl", rank=local_rank_idx, world_size=world_size, timeout=timedelta(minutes=30))  # 初始化分布式进程组
    torch_npu.npu.set_device(local_rank_idx)  # 设置当前使用的 NPU 设备

    device_id = f"npu:{local_rank_idx}"  # NPU 设备标识

    model = ToyModel().to(device_id)  # 实例化模型并移动到指定设备
    
    model = DDP(model)  # 包装模型以支持分布式训练

官方启动脚本:

#!/bin/bash

# 设置环境变量
export MASTER_ADDR="localhost"
export MASTER_PORT="12345"
export WORLD_SIZE=8  # 总的NPU数量

# 启动多个进程
for ((local_rank=0; local_rank<$WORLD_SIZE; local_rank++))
do
    export LOCAL_RANK=$local_rank
    python train_8p_shell.py &
done

wait

这里的需要注意的是,在Notebook里的并不是运行时的local_rank=1,而应该依然是local_rank=0,Notebook里监控的启动每次的起始序号不需要管它。

由于不是很熟悉这两个方法,让Claude写了根据参考资料个写了个demo脚本,虽然能运行,但是NPU的占用率起不来,查看了翻译的代码,有些逻辑和原始的对不上,存在和原始的文件对齐的问题还需要进一步修改。

总结

1.目前在学习accelerate和DDP之间的适配NPU问题。

2.虽然目前有个简单的demo可以运行,但是效率还需要改进。

3.根据文档学习还有没有别的方法更好的方法实现多卡。

更新时间:

留下评论