文档

使用竞价实例

更新时间:

当您选择使用通用计算资源公共资源组创建DLC任务时,您可以启用竞价实例功能。系统会自动选择更经济的竞价实例,以降低任务的运行成本。本文为您介绍使用竞价实例运行DLC任务的适用场景和操作实践。

前提条件

如果您需要使用竞价实例,请联系您的商务经理为您的账号开通白名单。

背景信息

阿里云为所有阿里云用户提供了一定数量的竞价实例(抢占实例,即一系列的CPU、GPU实例资源组),供所有阿里云用户共同抢占使用,此类实例的详情请参见什么是抢占式实例。运行DLC深度学习任务时,通过联系我们,进行相关设置,您也可以选用竞价实例,相比于普通的公共资源组实例(按量付费实例),竞价实例价格上通常有一定幅度的折扣,使用方法和计算能力与按量计费的实例无异,这可以帮助您以更低的成本获得AI计算能力,降低任务运行的资源成本。

由于竞价实例为所有阿里云用户共同抢占使用,抢占成功后有一段时间的保护期,超过保护期后阿里云会自动回收这些折扣售卖的实例,因此使用竞价实例运行DLC任务时,您需要关注任务运行时间,超过保护期后任务有可能因为资源被回收而运行失败。

应用场景

建议以下场景来使用竞价实例来降低成本:

  • 运行时间比较短的计算任务。

  • Debug状态的计算任务。

  • 能够容忍过程中失败的计算任务,如hyper-parameter search的子任务等。

  • 可中断和继续训练的计算任务,如经常做checkpoint并从checkpoint中继续的场景。

注意事项

由于竞价实例为阿里云所有用户共同抢占,不是稳定承诺可用的计算资源,因此使用竞价实例运行DLC任务时,需关注以下注意事项。

  • 资源申请:

    使用竞价实例的DLC任务提交后,DLC即开始为用户抢占实例资源,当阿里云的竞价实例资源库存不足时,有可能存在不能立即抢占到竞价实例资源的情况,此时DLC会持续为您申请抢占实例,在此阶段任务会表现为等待状态。

  • 资源回收:

    申请到竞价实例后,DLC任务即开始创建并运行,由于竞价实例超出保护期后会被回收,因此可能存在运行DLC任务时长超过保护期后,任务资源由于超过保护期在无提示下被回收,此时任务表现为失败结束。

  • 资源计费:

    阿里云竞价实例的出价模式包含使用自动出价(SpotAsPriceGo)和设置您的最高价(SpotWithPriceLimit)两种,DLC任务使用竞价实例时,使用自动出价的出价模式,即实例价格随着当前市场价动态变化,因此即使提交两个一模一样的任务,使用一模一样的资源持续相同的时间,其账单价格也可能不一样。

操作步骤

以下以一个具体的实践案例,为您示意使用竞价实例创建提交任务的操作步骤。

本案例是一个使用竞价实例,使用mnist数据集训练PyTorch任务,任务代码文件存储在Git中,任务运行中无需数据存储,创建任务时可以使用社区或PAI平台的PyTorch镜像,整个过程在P100机器(ecs.gn5-c4g1.xlarge)上花费约15分钟的时间。

  1. 任务代码配置。

    1. 准备任务代码文件。

      将下列代码保存为名称mnist.py的代码文件。

      from __future__ import print_function
      import argparse
      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      from torchvision import datasets, transforms
      from torch.optim.lr_scheduler import StepLR
      
      
      class Net(nn.Module):
          def __init__(self):
              super(Net, self).__init__()
              self.conv1 = nn.Conv2d(1, 32, 3, 1)
              self.conv2 = nn.Conv2d(32, 64, 3, 1)
              self.dropout1 = nn.Dropout(0.25)
              self.dropout2 = nn.Dropout(0.5)
              self.fc1 = nn.Linear(9216, 128)
              self.fc2 = nn.Linear(128, 10)
      
          def forward(self, x):
              x = self.conv1(x)
              x = F.relu(x)
              x = self.conv2(x)
              x = F.relu(x)
              x = F.max_pool2d(x, 2)
              x = self.dropout1(x)
              x = torch.flatten(x, 1)
              x = self.fc1(x)
              x = F.relu(x)
              x = self.dropout2(x)
              x = self.fc2(x)
              output = F.log_softmax(x, dim=1)
              return output
      
      
      def train(args, model, device, train_loader, optimizer, epoch):
          model.train()
          for batch_idx, (data, target) in enumerate(train_loader):
              data, target = data.to(device), target.to(device)
              optimizer.zero_grad()
              output = model(data)
              loss = F.nll_loss(output, target)
              loss.backward()
              optimizer.step()
              if batch_idx % args.log_interval == 0:
                  print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                      epoch, batch_idx * len(data), len(train_loader.dataset),
                      100. * batch_idx / len(train_loader), loss.item()))
                  if args.dry_run:
                      break
      
      
      def test(model, device, test_loader):
          model.eval()
          test_loss = 0
          correct = 0
          with torch.no_grad():
              for data, target in test_loader:
                  data, target = data.to(device), target.to(device)
                  output = model(data)
                  test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
                  pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
                  correct += pred.eq(target.view_as(pred)).sum().item()
      
          test_loss /= len(test_loader.dataset)
      
          print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
              test_loss, correct, len(test_loader.dataset),
              100. * correct / len(test_loader.dataset)))
      
      
      def main():
          # Training settings
          parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
          parser.add_argument('--batch-size', type=int, default=64, metavar='N',
                              help='input batch size for training (default: 64)')
          parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',
                              help='input batch size for testing (default: 1000)')
          parser.add_argument('--epochs', type=int, default=1, metavar='N',
                              help='number of epochs to train (default: 1)')
          parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
                              help='learning rate (default: 1.0)')
          parser.add_argument('--gamma', type=float, default=0.7, metavar='M',
                              help='Learning rate step gamma (default: 0.7)')
          parser.add_argument('--no-cuda', action='store_true', default=False,
                              help='disables CUDA training')
          parser.add_argument('--dry-run', action='store_true', default=False,
                              help='quickly check a single pass')
          parser.add_argument('--seed', type=int, default=1, metavar='S',
                              help='random seed (default: 1)')
          parser.add_argument('--log-interval', type=int, default=10, metavar='N',
                              help='how many batches to wait before logging training status')
          parser.add_argument('--save-model', action='store_true', default=False,
                              help='For Saving the current Model')
          args = parser.parse_args()
          use_cuda = not args.no_cuda and torch.cuda.is_available()
      
          torch.manual_seed(args.seed)
      
          device = torch.device("cuda" if use_cuda else "cpu")
      
          train_kwargs = {'batch_size': args.batch_size}
          test_kwargs = {'batch_size': args.test_batch_size}
          if use_cuda:
              cuda_kwargs = {'num_workers': 1,
                             'pin_memory': True,
                             'shuffle': True}
              train_kwargs.update(cuda_kwargs)
              test_kwargs.update(cuda_kwargs)
      
          transform=transforms.Compose([
              transforms.ToTensor(),
              transforms.Normalize((0.1307,), (0.3081,))
              ])
          dataset1 = datasets.MNIST('../data', train=True, download=True,
                             transform=transform)
          dataset2 = datasets.MNIST('../data', train=False,
                             transform=transform)
          train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs)
          test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs)
      
          model = Net().to(device)
          optimizer = optim.Adadelta(model.parameters(), lr=args.lr)
      
          scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma)
          for epoch in range(1, args.epochs + 1):
              train(args, model, device, train_loader, optimizer, epoch)
              test(model, device, test_loader)
              scheduler.step()
      
          if args.save_model:
              torch.save(model.state_dict(), "mnist_cnn.pt")
      
      
      if __name__ == '__main__':
          main()
    2. 上传代码文件至代码仓中(Git代码文件存储目录),用于后续在任务配置中引用运行。

      您可以将上述代码文件上传至自己的代码仓库,或者上传至以下开源的代码仓库中。

      https://github.com/WencongXiao/pytorch-demo.git
  2. DLC上配置任务代码。

    进入工作空间,将上述存有代码文件的代码仓信息配置到AI资产管理的代码配置页中,便于后续创建任务时直接引用,操作详情请参见步骤四:准备代码集。使用上述开源代码仓时,请参见以下示意配置进行配置。image.png

  3. 创建任务。

    DLC的任务列表页面创建任务,操作详情请参见提交任务(通过控制台)。本实践示例中的配置要点如下。

    1. 配置基本信息。

      • 节点镜像:本示例可选择社区镜像或PAI平台镜像中的PyTorch镜像。

      • 框架:本示例选择PyTorch

      • 代码配置:本示例选择上述步骤2中创建的任务代码配置。

      • 执行命令:本示例的执行命令可配置为:python /root/code/pytorch-demo/mnist.py

    2. 配置资源。

      • 资源配额:选择公共资源组

      • 框架:本示例选择Pytorch

      • 任务资源资源规格选择GPU > ecs.gn6e-c12g1.3xlarge;并选中竞价实例复选框。

    3. 完成任务配置后,单击提交

      任务提交后,DLC即开始申请抢占竞价实例,创建并运行任务。如果未抢占到竞价实例,此任务会显示为等待状态。

查看执行结果

成功创建运行任务后,在分布式训练任务列表,单击任务名称进入任务详情页面。在该页面查看任务的运行结果及详情。

说明

如果任务运行过程中,任务运行时长超过竞价实例的保护期,则资源可能被回收,导致任务运行失败。如果选择的节点库存不足,也可能导致节点失败。

查看账单明细

任务成功执行后,您可以在任务执行后的第二天访问费用中心页面,查看使用竞价实例执行该任务的费用明细,并与当前ECS按量计费价格进行对比。可见使用竞价实例的费用更低、更经济。查看账单明细的操作请参见账单明细

以下以一个运行案例作为参考,对比竞价实例与普通资源的价格情况。

说明
  • 后付费账单以T+1的形式产生,您可以在任务运行成功后的第二天查看账单明细。

  • 以下价格为某个时刻的价格参考,不同时间不同区域的实例报价可能有差异。

实例类型

规格与型号

参考价格

成本预估

竞价实例

  • GPU 型号:NVIDIA P100

  • 规格:ecs.gn5-c4g1.xlarge * 2

5.7706元

使用竞价实例可节约成本4.99倍。

普通ECS实例

28.782元

  • 本页导读 (1)
文档反馈