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

深度学习的多主机多GPU协同训练

来源于wetab AI-4o,未经验证,仅记录,供研究

A:  请介绍比较新的和先进的多主机多GPU训练方法

Q:  在现代深度学习中,多主机多GPU训练已经变得非常常见,尤其是对于大规模模型和数据集。除了PyTorch的DistributedDataParallel(DDP)之外,还有一些其他先进的方法和工具可以用于多主机多GPU训练。        以下是一些比较新的和先进的方法:

1. Horovod

Horovod 是一个由Uber开源的分布式训练框架,专门针对多GPU和多主机环境进行了优化。它支持TensorFlow、PyTorch和MxNet等多种深度学习框架。

特点
  • 易于使用:可以通过简单的API调用进行分布式训练。
  • 高性能:使用NCCL进行高效的GPU通信。
  • 灵活性:支持多种通信后端,包括MPI。
  • 容错性:支持进程动态加入和退出,提高了容错性。
安装
pip install horovod

示例代码(PyTorch)
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
import horovod.torch as hvd

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(10, 5)

    def forward(self, x):
        return self.linear(x)

class SimpleDataset(Dataset):
    def __init__(self, data, targets):
        self.data = data
        self.targets = targets

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]

def train():
    # 初始化Horovod
    hvd.init()

    # 设置当前进程的GPU设备
    torch.cuda.set_device(hvd.local_rank())

    # 创建模型并将其移动到指定的GPU
    model = SimpleModel().cuda()

    # 创建优化器并使用Horovod包装
    optimizer = optim.SGD(model.parameters(), lr=0.01 * hvd.size())
    optimizer = hvd.DistributedOptimizer(optimizer, named_parameters=model.named_parameters())

    # 载入数据
    dataset = SimpleDataset(torch.randn(1000, 10), torch.randint(0, 2, (1000, 5)))
    sampler = torch.utils.data.distributed.DistributedSampler(dataset, num_replicas=hvd.size(), rank=hvd.rank())
    dataloader = DataLoader(dataset, batch_size=32, sampler=sampler)

    # 训练循环
    for epoch in range(10):
        sampler.set_epoch(epoch)
        for batch_idx, (data, target) in enumerate(dataloader):
            optimizer.zero_grad()
            output = model(data.cuda())
            loss = nn.MSELoss()(output, target.cuda())
            loss.backward()
            optimizer.step()
            if batch_idx % 10 == 0 and hvd.rank() == 0:
                print(f'Epoch {epoch}, Batch {batch_idx}, Loss {loss.item()}')

if __name__ == "__main__":
    train()

2. DeepSpeed

DeepSpeed 是由Microsoft开源的一个深度学习优化库,特别适用于大规模模型的训练。它提供了多种优化技术,包括内存优化、梯度累积、混合精度训练等。

特点
  • 高性能:支持多种优化技术,大幅提高训练效率。
  • 易用性:通过简单的配置文件进行优化,无需修改大量代码。
  • 大规模模型支持:特别适合训练超过几十亿参数的大模型。
安装
pip install deepspeed

示例代码(PyTorch)
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
import deepspeed

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(10, 5)

    def forward(self, x):
        return self.linear(x)

class SimpleDataset(Dataset):
    def __init__(self, data, targets):
        self.data = data
        self.targets = targets

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]

def train():
    # 创建模型
    model = SimpleModel()

    # 创建优化器
    optimizer = optim.SGD(model.parameters(), lr=0.01)

    # 创建数据集和数据加载器
    dataset = SimpleDataset(torch.randn(1000, 10), torch.randint(0, 2, (1000, 5)))
    dataloader = DataLoader(dataset, batch_size=32)

    # 使用DeepSpeed初始化模型和优化器
    model_engine, optimizer, _, _ = deepspeed.initialize(model=model, optimizer=optimizer, args=None)

    # 训练循环
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(dataloader):
            data, target = data.to(model_engine.local_rank), target.to(model_engine.local_rank)
            output = model_engine(data)
            loss = nn.MSELoss()(output, target)
            model_engine.backward(loss)
            model_engine.step()
            if batch_idx % 10 == 0 and model_engine.local_rank == 0:
                print(f'Epoch {epoch}, Batch {batch_idx}, Loss {loss.item()}')

if __name__ == "__main__":
    train()

3. Megatron-LM

Megatron-LM 是一个由NVIDIA开源的高效并行化库,特别适用于大规模语言模型的训练。它提供了模型并行、数据并行和流水线并行等多种并行策略。

特点
  • 高效并行:支持多种并行策略,大幅提高训练速度。
  • 大规模模型支持:特别适合训练超过几百亿参数的模型。
  • 灵活的并行策略:可以根据模型和硬件配置灵活选择并行策略。
安装
pip install megatron-lm

示例代码
import torch
import torch.distributed as dist
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset
from megatron import get_args, initialize_megatron, mpu

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(10, 5)

    def forward(self, x):
        return self.linear(x)

class SimpleDataset(Dataset):
    def __init__(self, data, targets):
        self.data = data
        self.targets = targets

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]

def train():
    # 初始化Megatron
    args = get_args()
    initialize_megatron(backend='nccl', world_size=args.world_size, rank=args.rank, tensor_model_parallel_size=args.tensor_model_parallel_size, pipeline_model_parallel_size=args.pipeline_model_parallel_size)

    # 创建模型并将其移动到指定的GPU
    model = SimpleModel().cuda()

    # 创建优化器
    optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

    # 创建数据集和数据加载器
    dataset = SimpleDataset(torch.randn(1000, 10), torch.randint(0, 2, (1000, 5)))
    dataloader = DataLoader(dataset, batch_size=32)

    # 训练循环
    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(dataloader):
            data, target = data.cuda(), target.cuda()
            output = model(data)
            loss = nn.MSELoss()(output, target)
            loss.backward()
            optimizer.step()
            if batch_idx % 10 == 0 and mpu.get_data_parallel_rank() == 0:
                print(f'Epoch {epoch}, Batch {batch_idx}, Loss {loss.item()}')

if __name__ == "__main__":
    # 解析命令行参数
    parser = argparse.ArgumentParser()
    parser.add_argument("--rank", type=int, required=True)
    parser.add_argument("--world-size", type=int, required=True)
    parser.add_argument("--tensor-model-parallel-size", type=int, default=1)
    parser.add_argument("--pipeline-model-parallel-size", type=int, default=1)
    args = parser.parse_args()

    # 设置环境变量
    os.environ["MASTER_ADDR"] = "192.168.1.1"
    os.environ["MASTER_PORT"] = "1234"

    train()

4. PyTorch Elastic

PyTorch Elastic 是PyTorch的一个扩展,用于在动态集群环境中进行分布式训练。它支持自动的规模扩展和容错性。

特点
  • 动态扩展:支持训练过程中动态增加或减少计算资源。
  • 容错性:支持进程动态加入和退出,提高了容错性。
示例代码
import torch
import torch.distributed as dist
import torch.nn as nn
import torch.optim as optim
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.data import DataLoader, Dataset
import argparse

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(10, 5)

    def forward(self, x):
        return self.linear(x)

class SimpleDataset(Dataset):
    def __init__(self, data, targets):
        self.data = data
        self.targets = targets

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]

def train(rank, world_size, backend):
    dist.init_process_group(backend, rank=rank, world_size=world_size)
    torch.cuda.set_device(rank)

    # 创建模型并将其移动到指定的GPU
    model = SimpleModel().to(rank)
    ddp_model = DDP(model, device_ids=[rank])

    # 创建优化器
    optimizer = optim.SGD(ddp_model.parameters(), lr=0.01)

    # 创建数据集和数据加载器
    dataset = SimpleDataset(torch.randn(1000, 10), torch.randint(0, 2, (1000, 5)))
    sampler = torch.utils.data.distributed.DistributedSampler(dataset)
    dataloader = DataLoader(dataset, batch_size=32, sampler=sampler)

    # 训练循环
    for epoch in range(10):
        sampler.set_epoch(epoch)
        for batch_idx, (data, target) in enumerate(dataloader):
            optimizer.zero_grad()
            output = ddp_model(data)
            loss = nn.MSELoss()(output, target.to(rank))
            loss.backward()
            optimizer.step()
            if batch_idx % 10 == 0 and rank == 0:
                print(f'Epoch {epoch}, Batch {batch_idx}, Loss {loss.item()}')

    dist.destroy_process_group()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--rank", type=int, required=True)
    parser.add_argument("--world-size", type=int, required=True)
    parser.add_argument("--backend", type=str, default="nccl")
    args = parser.parse_args()

    train(args.rank, args.world_size, args.backend)

5. Ray

Ray 是一个用于构建分布式应用程序的框架,支持分布式训练、超参数调优等任务。

特点
  • 灵活性:支持多种深度学习框架和库。
  • 高性能:提供了高效的分布式调度和通信机制。
  • 易用性:通过高级API简化分布式应用的开发。
示例代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
import ray
from ray.util import ActorPool

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(10, 5)

    def forward(self, x):
        return self.linear(x)

class SimpleDataset(Dataset):
    def __init__(self, data, targets):
        self.data = data
        self.targets = targets

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]

@ray.remote(num_gpus=1)
class Worker:
    def __init__(self, rank, world_size):
        self.rank = rank
        self.world_size = world_size
        self.device = torch.device(f"cuda:{self.rank}")

        # 创建模型并将其移动到指定的GPU
        self.model = SimpleModel().to(self.device)

        # 创建优化器
        self.optimizer = optim.SGD(self.model.parameters(), lr=0.01)

        # 创建数据集和数据加载器
        dataset = SimpleDataset(torch.randn(1000, 10), torch.randint(0, 2, (1000, 5)))
        self.dataloader = DataLoader(dataset, batch_size=32)

    def train_step(self, data, target):
        self.optimizer.zero_grad()
        output = self.model(data.to(self.device))
        loss = nn.MSELoss()(output, target.to(self.device))
        loss.backward()
        self.optimizer.step()
        return loss.item()

def train(world_size):
    workers = [Worker.remote(i, world_size) for i in range(world_size)]
    pool = ActorPool(workers)

    for epoch in range(10):
        for batch_idx, (data, target) in enumerate(dataloader):
            losses = list(pool.map(lambda w, v: w.train_step.remote(v[0], v[1]), [(data, target)] * world_size))
            avg_loss = sum(losses) / len(losses)
            if batch_idx % 10 == 0:
                print(f'Epoch {epoch}, Batch {batch_idx}, Average Loss {avg_loss}')

if __name__ == "__main__":
    ray.init()

    world_size = 2  # 假设有两块GPU
    train(world_size)

    ray.shutdown()

结论

        这些先进的多主机多GPU训练方法各有特点,适用的场景也有所不同。选择哪种方法取决于你的具体需求和硬件配置:

  • Horovod:简单易用,支持多种深度学习框架,适合中小规模的分布式训练。
  • DeepSpeed:提供多种优化技术,特别适合大规模模型的训练。
  • Megatron-LM:高效的并行策略,特别适合大规模语言模型的训练。
  • PyTorch Elastic:支持动态扩展和容错性,适合在云环境中进行分布式训练。
  • Ray:灵活性高,支持多种任务,适合构建复杂的分布式应用程序。

http://www.kler.cn/a/402062.html

相关文章:

  • kvm-dmesg:从宿主机窥探虚拟机内核dmesg日志
  • 软件设计师 - 第3章 数据结构
  • java8 快捷方式
  • LabVIEW 温湿度测试与监控系统
  • https(day30)
  • 高效工具推荐:基于WebGPU的Whisper Web结合内网穿透远程使用指南
  • 【C++学习(37)】并发性模式:如生产者-消费者、读写锁等。 架构模式:如MVC、MVVM等。属于23 种设计模式吗? RAII 的关系?
  • 传奇996_23——杀怪掉落,自动捡取,捡取动画
  • Ribbon 与 Feign:微服务调用中的差异探究
  • Linux网络——套接字编程
  • 学习记录:js算法(九十五):被围绕的区域
  • 2019年下半年试题二:论软件系统架构评估及其应用
  • Node.js | Yarn下载安装与环境配置
  • 【JAVA】正则表达式中的正向肯定预查
  • Java安全—log4j日志FastJson序列化JNDI注入
  • 创新租赁APP开发提升用户体验与业务效率
  • 【经典】webpack和vite的区别?
  • D - Strange Mirroring(AtCoder Beginner Contest 380)
  • ServletConfig、ServletContext、HttpServletRequest与HttpServletResponse常见API
  • 记录———封装uni-app+vant(u-upload)上传图片组件
  • windows C#-编写 C# LINQ 查询(上)
  • IPv6 NDP 记录
  • vue2侧边导航栏路由
  • 三、计算机视觉_02计算机视觉领域的四大基本任务
  • AI 无人直播常见问题剖析:轻松一键开播,畅行智能直播新时代
  • 第T8周:Tensorflow实现猫狗识别(1)