Todos los productos
Search
Centro de documentos

Platform For AI:Quick start: Distributed training with DLC

Última actualización: Sep 04, 2026

Deep Learning Containers (DLC) le permite crear rápidamente trabajos de entrenamiento en un solo nodo o distribuidos sin aprovisionar máquinas ni configurar entornos manualmente. Este tutorial demuestra el proceso integral tanto para el entrenamiento en un solo nodo con una sola GPU como para el entrenamiento multinodo con múltiples GPU, mediante la tarea de reconocimiento de dígitos manuscritos MNIST.

Nota

El reconocimiento de dígitos manuscritos MNIST es una tarea introductoria clásica en el aprendizaje profundo. El objetivo es construir un modelo de aprendizaje automático que reconozca 10 dígitos manuscritos (del 0 al 9).

1. Requisitos previos

Utilice su cuenta principal para activar PAI y crear un espacio de trabajo. Inicie sesión en la PAI console, seleccione una región en la esquina superior izquierda y siga las indicaciones para otorgar permisos y activar el servicio.

2. Facturación

Los ejemplos de este tutorial utilizan recursos públicos para crear trabajos de DLC, los cuales se facturan bajo el modelo pay-as-you-go. Para obtener más información, consulte Billing for Deep Learning Containers (DLC).

3. Entrenamiento en un solo nodo con una sola GPU

3.1 Crear un conjunto de datos

Un conjunto de datos almacena su código de entrenamiento, datos y artefactos del modelo. Esta sección explica cómo utilizar un conjunto de datos basado en Alibaba Cloud Object Storage Service (OSS).

  1. En el panel de navegación izquierdo de la PAI console, vaya a Datasets > Custom Dataset > Create datasets.

  2. Configure los siguientes parámetros clave y conserve los valores predeterminados para el resto.

    • Name: Por ejemplo, introduzca dataset_mnist.

    • Storage Type: Seleccione OSS.

    • OSS Path: Haga clic en el icono de carpeta image, seleccione un bucket y cree un nuevo directorio, como dlc_mnist.

      Si no ha activado OSS o no tiene un bucket disponible en la región actual, siga estos pasos para activar OSS y crear un bucket:

      (Opcional) Activar OSS y crear un bucket

      1. Activar OSS.

      2. Log on to the OSS console, haga clic en Create Bucket, introduzca un Bucket name y seleccione la misma Region que en PAI. Conserve los valores predeterminados para los demás parámetros y haga clic en Create.

    Haga clic en Confirm para crear el conjunto de datos.

  3. Cargue el código de entrenamiento y los datos.

    1. Descargue el script de entrenamiento proporcionado: mnist_train.py. Para simplificar el proceso, el script descarga automáticamente los datos de entrenamiento al directorio dataSet de su conjunto de datos durante la ejecución.

      Para sus propios proyectos, puede precargar su código y datos de entrenamiento en un conjunto de datos de PAI.

      Ejemplo de código de entrenamiento en un solo nodo con una sola GPU: mnist_train.py

      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      from torch.utils.data import DataLoader
      from torchvision import datasets, transforms
      from torch.utils.tensorboard import SummaryWriter
      # Hyperparameters
      batch_size = 64  # Batch size for each training iteration
      learning_rate = 0.01  # Learning rate
      num_epochs = 20  # Number of training epochs
      # Check if a GPU is available
      device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
      # Data preprocessing
      transform = transforms.Compose([
          transforms.ToTensor(),
          transforms.Normalize((0.5,), (0.5,))
      ])
      train_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=True, download=True, transform=transform)
      val_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=False, download=False, transform=transform)
      train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
      val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
      # Define a simple neural network
      class SimpleCNN(nn.Module):
          def __init__(self):
              super(SimpleCNN, self).__init__()
              # First convolutional layer: 1 input channel (grayscale image), 10 output channels, 5x5 kernel
              self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
              # Second convolutional layer: 10 input channels, 20 output channels, 3x3 kernel
              self.conv2 = nn.Conv2d(10, 20, kernel_size=3)
              # Fully connected layer: Input is 20 * 5 * 5 (feature map size after convolution and pooling), output is 128
              self.fc1 = nn.Linear(20 * 5 * 5, 128)
              # Output layer: 128 -> 10 (for 10 digit classes)
              self.fc2 = nn.Linear(128, 10)
          def forward(self, x):
              # Input x shape: [batch, 1, 28, 28]
              x = F.max_pool2d(F.relu(self.conv1(x)), 2)  # [batch, 10, 12, 12]
              x = F.max_pool2d(F.relu(self.conv2(x)), 2)  # [batch, 20, 5, 5]
              x = x.view(-1, 20 * 5 * 5)  # Flatten to [batch, 500]
              x = F.relu(self.fc1(x))      # [batch, 128]
              x = self.fc2(x)              # [batch, 10]
              return x
      # Instantiate the model and move it to the GPU if available
      model = SimpleCNN().to(device)
      criterion = nn.CrossEntropyLoss()
      optimizer = optim.SGD(model.parameters(), lr=learning_rate)
      # Create a TensorBoard SummaryWriter to visualize the model training process
      writer = SummaryWriter('/mnt/data/output/runs/mnist_experiment')
      # Variable to save the model with the highest accuracy
      best_val_accuracy = 0.0
      # Train the model and log loss and accuracy
      for epoch in range(num_epochs):
          model.train()
          for batch_idx, (data, target) in enumerate(train_loader):
              data, target = data.to(device), target.to(device)  # Move data and target to the GPU
              # Zero the gradients
              optimizer.zero_grad()
              # Forward pass
              output = model(data)
              # Calculate loss
              loss = criterion(output, target)
              # Backward pass
              loss.backward()
              # Update parameters
              optimizer.step()
              # Log training loss to TensorBoard
              if batch_idx % 100 == 0:  # Log every 100 batches
                  writer.add_scalar('Loss/train', loss.item(), epoch * len(train_loader) + batch_idx)
                  print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} ({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}')
          # Validate the model and log validation loss and accuracy
          model.eval()
          val_loss = 0
          correct = 0
          with torch.no_grad():  # Do not calculate gradients
              for data, target in val_loader:
                  data, target = data.to(device), target.to(device)  # Move data and target to the GPU
                  output = model(data)
                  val_loss += criterion(output, target).item()  # Accumulate validation loss
                  pred = output.argmax(dim=1, keepdim=True)  # Get predicted label
                  correct += pred.eq(target.view_as(pred)).sum().item()  # Accumulate number of correct predictions
          val_loss /= len(val_loader)  # Calculate average validation loss
          val_accuracy = 100. * correct / len(val_loader.dataset)  # Calculate validation accuracy
          print(f'Validation Loss: {val_loss:.4f}, Accuracy: {correct}/{len(val_loader.dataset)} ({val_accuracy:.0f}%)')
          # Log validation loss and accuracy to TensorBoard
          writer.add_scalar('Loss/validation', val_loss, epoch)
          writer.add_scalar('Accuracy/validation', val_accuracy, epoch)
          # Save the model with the highest validation accuracy
          if val_accuracy > best_val_accuracy:
              best_val_accuracy = val_accuracy
              torch.save(model.state_dict(), '/mnt/data/output/best_model.pth')
              print(f'Model saved with accuracy: {best_val_accuracy:.2f}%')
      # Close the SummaryWriter
      writer.close()
      print('Training complete. writer.close()')
    2. Cargue el código. En la página de detalles del conjunto de datos, haga clic en View Data para ir a la consola de OSS. Luego, haga clic en Upload Object >Select Files > Upload Object para cargar el script de entrenamiento en OSS.

3.2 Crear un trabajo de DLC

  1. En el panel de navegación izquierdo de la PAI console, vaya a Deep Learning Containers (DLC) > Create Job.

  2. Configure los siguientes parámetros clave y conserve los valores predeterminados para el resto. Para ver la lista completa de parámetros, consulte Create a training job.

    • Image Configuration: Seleccione Image Address y luego introduzca la dirección de imagen correspondiente a su Region.

      En la barra de navegación superior de la consola, utilice el selector de Region para confirmar su región actual, por ejemplo, China (Hangzhou).

      Región

      Dirección de imagen

      China (Beijing)

      dsw-registry-vpc.cn-beijing.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      China (Shanghai)

      dsw-registry-vpc.cn-shanghai.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      China (Hangzhou)

      dsw-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      Otra

      Find your region ID y reemplace <Region ID> en la dirección de la imagen para obtener la URL completa:

      dsw-registry-vpc.<Region ID>.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      Esta imagen utiliza el mismo entorno verificado del tema Get Started with DSW Interactive Modeling . Al trabajar con modelos en PAI, un flujo de trabajo típico consiste en verificar primero el entorno y desarrollar el código en DSW, y luego usar DLC para el entrenamiento.
    • Dataset Mount: Seleccione Custom Dataset y elija el conjunto de datos que creó en el paso anterior. La Mount Path predeterminada es /mnt/data.

    • Startup Command: python /mnt/data/mnist_train.py

      El comando de inicio es el mismo que cuando ejecuta el código en DSW o localmente. Sin embargo, dado que mnist_train.py ahora está montado en /mnt/data/ , solo necesita cambiar la ruta del código a /mnt/data/mnist_train.py .
    • Source: Seleccione Public Resources y luego seleccione ecs.gn7i-c8g1.2xlarge para el Resource Type.

      Si este tipo de instancia no está disponible, puede elegir otro tipo de instancia con GPU.

    Haga clic en OK para crear el trabajo. El trabajo tarda aproximadamente 15 minutos en ejecutarse. Durante la ejecución, puede hacer clic en Logs para ver el progreso del entrenamiento.

    El registro de entrenamiento muestra que el modelo MNIST alcanza una precisión de validación de 9886/10000 (aproximadamente 99%) en la época 18. Cuando el estado del trabajo cambia a Succeeded, el registro muestra la salida final: Training complete. writer.close().

    Una vez completado el trabajo, DLC guarda el mejor punto de control del modelo y el registro de TensorBoard en la ruta output del conjunto de datos montado.

    El directorio dlc_mnist/ en su bucket de OSS ahora contiene un subdirectorio dataSet/ para los datos de entrenamiento, un subdirectorio output/ para los artefactos del modelo y el script mnist_train.py.

3.3 (Opcional) Visualización en TensorBoard

Puede utilizar la herramienta de visualización TensorBoard para consultar la curva de pérdida y comprender mejor el proceso de entrenamiento.

Importante

Para usar TensorBoard con un trabajo de DLC, debe configurar un conjunto de datos.

  1. En la página de detalles del trabajo de DLC, haga clic en la pestaña Tensorboard y luego haga clic en Create TensorBoard.

  2. Establezca Configuration Type en By Task. Para Summary Path, introduzca la ruta donde SummaryWriter guarda los datos en el código de entrenamiento: /mnt/data/output/runs/. Haga clic en OK para iniciar.

    Esto corresponde al fragmento de código: writer = SummaryWriter('/mnt/data/output/runs/mnist_experiment')
  3. Haga clic en View TensorBoard para ver la curva train_loss (pérdida del conjunto de entrenamiento) y la curva validation_loss (pérdida del conjunto de validación).

    image

    (Opcional) Ajustar hiperparámetros para mejorar el rendimiento del modelo

    Puede evaluar el rendimiento de su modelo observando las tendencias en los valores de pérdida:

    • Las métricas train_loss y validation_loss aún muestran una tendencia descendente antes de que termine el entrenamiento (subajuste).

      Puede aumentar num_epochs (el número de épocas de entrenamiento) o incrementar ligeramente learning_rate y luego volver a entrenar el modelo para ajustarlo mejor a los datos de entrenamiento.

    • La métrica train_loss disminuye continuamente, pero validation_loss comienza a aumentar antes de que termine el entrenamiento (sobreajuste).

      Puede disminuir num_epochs o reducir ligeramente learning_rate y luego volver a entrenar el modelo para evitar el sobreajuste.

    • Tanto train_loss como validation_loss se mantienen estables antes de que termine el entrenamiento (buen ajuste).

      Cuando el modelo se encuentra en este estado, puede continuar con los siguientes pasos.

3.4 Desplegar el modelo entrenado

Para obtener más información, consulte V. Use EAS to deploy model services.

4. Entrenamiento distribuido con múltiples GPU

Si una sola GPU no tiene memoria suficiente para su modelo o desea acelerar el entrenamiento, cree un trabajo de entrenamiento distribuido con múltiples GPU o multinodo.

Esta sección utiliza dos instancias, cada una con una sola GPU, como ejemplo. El mismo procedimiento se aplica a otras configuraciones de múltiples GPU y multinodo.

4.1 Preparar el conjunto de datos y el script

Si ya creó un conjunto de datos en la sección 3. Single-node, single-GPU training, simplemente descargue mnist_train_distributed.py y cárguelo. De lo contrario, primero 3.1 Create a dataset y luego cargue el código.

Ejemplo de código de entrenamiento multinodo con múltiples GPU o en un solo nodo con múltiples GPU: mnist_train_distributed.py

import os
import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torch.utils.data.distributed import DistributedSampler
from torchvision import datasets, transforms
from torch.utils.tensorboard import SummaryWriter
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=3)
        self.fc1 = nn.Linear(20 * 5 * 5, 128)
        self.fc2 = nn.Linear(128, 10)
    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), 2)
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, 20 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x
def main():
    rank = int(os.environ["RANK"])
    world_size = int(os.environ["WORLD_SIZE"])
    local_rank = int(os.environ["LOCAL_RANK"])
    dist.init_process_group(backend='nccl')
    torch.cuda.set_device(local_rank)
    device = torch.device('cuda', local_rank)
    batch_size = 64
    learning_rate = 0.01
    num_epochs = 20
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    # Only the main process (rank=0) needs to download; other processes must wait for it.
    # Make processes with rank != 0 wait at the barrier.
    if rank != 0:
        dist.barrier()
    # All processes create the dataset.
    # However, only the rank 0 process actually performs the download.
    train_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=True, download=(rank == 0), transform=transform)
    # After the rank 0 process finishes downloading, it also reaches the barrier, releasing all processes.
    if rank == 0:
        dist.barrier()
    # At this point, all processes are synchronized and can continue.
    val_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=False, download=False, transform=transform)
    train_sampler = DistributedSampler(train_dataset, num_replicas=world_size, rank=rank, shuffle=True)
    train_loader = DataLoader(train_dataset, batch_size=batch_size, sampler=train_sampler, num_workers=4, pin_memory=True)
    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True)
    model = SimpleCNN().to(device)
    model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank])
    criterion = nn.CrossEntropyLoss().to(device)
    optimizer = optim.SGD(model.parameters(), lr=learning_rate)
    if rank == 0:
        writer = SummaryWriter('/mnt/data/output_distributed/runs/mnist_experiment')
    best_val_accuracy = 0.0
    for epoch in range(num_epochs):
        train_sampler.set_epoch(epoch)
        model.train()
        for batch_idx, (data, target) in enumerate(train_loader):
            data, target = data.to(device, non_blocking=True), target.to(device, non_blocking=True)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            if batch_idx % 100 == 0:
                # Each rank and local_rank prints its own loss.
                print(f"Rank: {rank}, Local_Rank: {local_rank} -- Train Epoch: {epoch} "
                      f"[{batch_idx * len(data) * world_size}/{len(train_loader.dataset)} "
                      f"({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}")
                if rank == 0:
                    writer.add_scalar('Loss/train', loss.item(), epoch * len(train_loader) + batch_idx)
        # Validation
        model.eval()
        val_loss = 0
        correct = 0
        total = 0
        with torch.no_grad():
            for data, target in val_loader:
                data, target = data.to(device, non_blocking=True), target.to(device, non_blocking=True)
                output = model(data)
                val_loss += criterion(output, target).item() * data.size(0)
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()
                total += target.size(0)
        val_loss_tensor = torch.tensor([val_loss], dtype=torch.float32, device=device)
        correct_tensor = torch.tensor([correct], dtype=torch.float32, device=device)
        total_tensor = torch.tensor([total], dtype=torch.float32, device=device)
        dist.all_reduce(val_loss_tensor, op=dist.ReduceOp.SUM)
        dist.all_reduce(correct_tensor, op=dist.ReduceOp.SUM)
        dist.all_reduce(total_tensor, op=dist.ReduceOp.SUM)
        val_loss = val_loss_tensor.item() / total_tensor.item()
        val_accuracy = 100. * correct_tensor.item() / total_tensor.item()
        if rank == 0:
            print(f'Validation Loss: {val_loss:.4f}, Accuracy: {int(correct_tensor.item())}/{int(total_tensor.item())} ({val_accuracy:.0f}%)')
            writer.add_scalar('Loss/validation', val_loss, epoch)
            writer.add_scalar('Accuracy/validation', val_accuracy, epoch)
            if val_accuracy > best_val_accuracy:
                best_val_accuracy = val_accuracy
                torch.save(model.module.state_dict(), '/mnt/data/output_distributed/best_model.pth')
                print(f'Model saved with accuracy: {best_val_accuracy:.2f}%')
    if rank == 0:
        writer.close()
    dist.destroy_process_group()
    if rank == 0:
        print('Training complete. writer.close()')
if __name__ == "__main__":
    main()

4.2 Crear un trabajo de DLC distribuido

  1. En el panel de navegación izquierdo de la PAI console, vaya a Deep Learning Containers (DLC) > Create Job.

  2. Configure los siguientes parámetros clave y conserve los valores predeterminados para el resto. Para ver la lista completa de parámetros, consulte Create a training job.

    • Image Configuration: Seleccione Image Address y luego introduzca la dirección de imagen correspondiente a su Region.

      Región

      Dirección de imagen

      China (Beijing)

      dsw-registry-vpc.cn-beijing.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      China (Shanghai)

      dsw-registry-vpc.cn-shanghai.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      China (Hangzhou)

      dsw-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      Otra

      Find your region ID y reemplace <Region ID> en la dirección de la imagen para obtener la URL completa:

      dsw-registry-vpc.<Region ID>.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      Esta imagen utiliza el mismo entorno verificado del tema Get Started with DSW Interactive Modeling . Al trabajar con modelos en PAI, un flujo de trabajo típico consiste en verificar primero el entorno y desarrollar el código en DSW, y luego usar DLC para el entrenamiento.
    • Dataset Mount: Seleccione Custom Dataset y elija el conjunto de datos que creó. La Mount Path predeterminada es /mnt/data.

    • Startup Command: torchrun --nproc_per_node=1 --nnodes=${WORLD_SIZE} --node_rank=${RANK} --master_addr=${MASTER_ADDR} --master_port=${MASTER_PORT} /mnt/data/mnist_train_distributed.py

      DLC inyecta automáticamente variables de entorno comunes de environment variables , como MASTER_ADDR y WORLD_SIZE , a las que puede acceder con la sintaxis $VARIABLE_NAME .
    • Source: Seleccione Public Resources, establezca Number of Nodes en 2 y seleccione ecs.gn7i-c8g1.2xlarge para el Resource Type.

      Si este tipo de instancia no está disponible, puede elegir otro tipo de instancia con GPU.

    Haga clic en Confirm para crear el trabajo. El trabajo tarda aproximadamente 10 minutos en ejecutarse. Durante la ejecución, puede consultar el Log de entrenamiento de ambas instancias en la página Overview.

    Una vez completado el trabajo, DLC guarda el mejor punto de control del modelo y el registro de TensorBoard en la ruta output_distributed del conjunto de datos montado.

4.3 (Opcional) Visualización en TensorBoard

Puede utilizar la herramienta de visualización TensorBoard para consultar la curva de pérdida y comprender mejor el proceso de entrenamiento.

Importante

Para usar TensorBoard con un trabajo de DLC, debe configurar un conjunto de datos.

  1. En la página de detalles del trabajo de DLC, haga clic en la pestaña TensorBoard y luego haga clic en Create TensorBoard.

  2. Establezca Configuration Type en By Task. Para Summary Path, introduzca la ruta donde el código de entrenamiento guarda los archivos de resumen: /mnt/data/output_distributed/runs. Haga clic en OK para iniciar.

    Esto corresponde al fragmento de código: writer = SummaryWriter('/mnt/data/output_distributed/runs/mnist_experiment')
  3. Haga clic en View TensorBoard para ver la curva train_loss (pérdida del conjunto de entrenamiento) y la curva validation_loss (pérdida del conjunto de validación).

    image

    (Opcional) Ajustar hiperparámetros para mejorar el rendimiento del modelo

    Puede evaluar el rendimiento de su modelo observando las tendencias en los valores de pérdida:

    • Antes de que termine el entrenamiento, train_loss y validation_loss siguen disminuyendo (subajuste).

      Puede aumentar num_epochs (el número de épocas de entrenamiento) o incrementar ligeramente learning_rate y luego volver a entrenar el modelo para ajustarlo mejor a los datos de entrenamiento.

    • La métrica train_loss disminuye continuamente, mientras que validation_loss comienza a aumentar antes de que termine el entrenamiento (sobreajuste).

      Puede disminuir num_epochs o reducir ligeramente learning_rate y luego volver a entrenar el modelo para evitar el sobreajuste.

    • Tanto train_loss como validation_loss se mantienen estables antes de que termine el entrenamiento (buen ajuste).

      Cuando el modelo se encuentra en este estado, puede continuar con los siguientes pasos.

4.4 Desplegar el modelo entrenado

Para obtener más información, consulte V. Deploying model services using EAS.

5. Información relacionada