

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Memodifikasi Skrip PyTorch Pelatihan
<a name="model-parallel-customize-training-script-pt"></a>

Di bagian ini, Anda mempelajari cara memodifikasi skrip PyTorch pelatihan untuk mengonfigurasi pustaka paralelisme SageMaker model untuk partisi otomatis dan partisi manual.

**catatan**  
Untuk menemukan PyTorch versi mana yang didukung oleh perpustakaan, lihat[Kerangka Kerja yang Didukung dan Wilayah AWS](distributed-model-parallel-support.md).

**Tip**  
Untuk contoh end-to-end buku catatan yang menunjukkan cara menggunakan skrip PyTorch pelatihan dengan pustaka paralelisme SageMaker model, lihat. [Contoh perpustakaan paralelisme model Amazon SageMaker AI v1](distributed-model-parallel-examples.md)

Perhatikan bahwa partisi otomatis diaktifkan secara default. Kecuali ditentukan lain, skrip berikut menggunakan partisi otomatis. 

**Topics**
+ [Pemisahan otomatis dengan PyTorch](#model-parallel-customize-training-script-pt-16)
+ [Pemisahan manual dengan PyTorch](#model-parallel-customize-training-script-pt-16-hvd)
+ [Pertimbangan-pertimbangan](#model-parallel-pt-considerations)
+ [Fitur kerangka kerja yang tidak didukung](#model-parallel-pt-unsupported-features)

## Pemisahan otomatis dengan PyTorch
<a name="model-parallel-customize-training-script-pt-16"></a>

Perubahan skrip pelatihan berikut diperlukan untuk menjalankan skrip PyTorch pelatihan dengan pustaka SageMaker paralelisme model:

1. Impor dan inisialisasi perpustakaan dengan [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#smp.init](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#smp.init).

1. Bungkus model dengan [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedModel](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedModel). Berhati-hatilah bahwa setiap tensor yang dikembalikan dari `forward` metode `nn.Module` objek yang mendasarinya akan disiarkan di seluruh perangkat model-paralel, menimbulkan overhead komunikasi, jadi tensor apa pun yang tidak diperlukan di luar metode panggilan (seperti aktivasi perantara) tidak boleh dikembalikan.
**catatan**  
Untuk FP16 pelatihan, Anda perlu menggunakan pengelola konteks [smdistributed.modelparallel.torch.model\$1creation](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/latest/smd_model_parallel_pytorch.html) () untuk membungkus model. Untuk informasi selengkapnya, lihat [FP16 Pelatihan dengan Model Paralelisme](model-parallel-extended-features-pytorch-fp16.md).

1. Bungkus pengoptimal dengan [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedOptimizer](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedOptimizer).
**catatan**  
Untuk FP16 pelatihan, Anda perlu mengatur penskalaan kerugian statis atau dinamis. Untuk informasi selengkapnya, lihat [FP16 Pelatihan dengan Model Paralelisme](model-parallel-extended-features-pytorch-fp16.md).

1. Gunakan `DistributedModel` objek yang dikembalikan alih-alih model pengguna.

1. Letakkan logika maju dan mundur dalam fungsi langkah dan hiasi dengan [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#smp.init](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#smp.init).

1. Batasi setiap proses ke perangkatnya sendiri melalui`torch.cuda.set_device(smp.local_rank())`.

1. Pindahkan tensor input ke GPU menggunakan `.to()` API sebelum `smp.step` panggilan (lihat contoh di bawah).

1. Ganti `torch.Tensor.backward` dan `torch.autograd.backward` dengan`DistributedModel.backward`.

1. Lakukan pasca-pemrosesan pada output di seluruh microbatch menggunakan [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#StepOutput](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#StepOutput)metode seperti. `reduce_mean`

1. [Jika ada langkah evaluasi, tempatkan logika penerusan di dalam fungsi `smp.step` -decorated dan pasca-proses output menggunakan API. `StepOutput`](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#StepOutput)

1. Ditetapkan `drop_last=True` di`DataLoader`. Atau, lewati batch secara manual dalam loop pelatihan jika ukuran batch tidak habis dibagi dengan jumlah microbatch.

Untuk mempelajari lebih lanjut tentang API pustaka paralelisme model, lihat dokumentasi [API](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smd_model_parallel.html). SageMaker 

```
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchnet.dataset import SplitDataset
from torchvision import datasets

import smdistributed.modelparallel.torch as smp

class GroupedNet(nn.Module):
    def __init__(self):
        super(GroupedNet, self).__init__()
        # define layers

    def forward(self, x):
        # define forward pass and return model outputs


# smdistributed: Define smp.step. Return any tensors needed outside.
@smp.step
def train_step(model, data, target):
    output = model(data)
    loss = F.nll_loss(output, target, reduction="mean")
    model.backward(loss)
    return output, loss


def train(model, device, train_loader, optimizer):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        # smdistributed: Move input tensors to the GPU ID used by the current process,
        # based on the set_device call.
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        # Return value, loss_mb is a StepOutput object
        _, loss_mb = train_step(model, data, target)

        # smdistributed: Average the loss across microbatches.
        loss = loss_mb.reduce_mean()

        optimizer.step()

# smdistributed: initialize the backend
smp.init()

# smdistributed: Set the device to the GPU ID used by the current process.
# Input tensors should be transferred to this device.
torch.cuda.set_device(smp.local_rank())
device = torch.device("cuda")

# smdistributed: Download only on a single process per instance.
# When this is not present, the file is corrupted by multiple processes trying
# to download and extract at the same time
dataset = datasets.MNIST("../data", train=True, download=False)

# smdistributed: Shard the dataset based on data-parallel ranks
if smp.dp_size() > 1:
    partitions_dict = {f"{i}": 1 / smp.dp_size() for i in range(smp.dp_size())}
    dataset = SplitDataset(dataset, partitions=partitions_dict)
    dataset.select(f"{smp.dp_rank()}")

# smdistributed: Set drop_last=True to ensure that batch size is always divisible
# by the number of microbatches
train_loader = torch.utils.data.DataLoader(dataset, batch_size=64, drop_last=True)

model = GroupedNet()
optimizer = optim.Adadelta(model.parameters(), lr=4.0)

# smdistributed: Use the DistributedModel container to provide the model
# to be partitioned across different ranks. For the rest of the script,
# the returned DistributedModel object should be used in place of
# the model provided for DistributedModel class instantiation.
model = smp.DistributedModel(model)
optimizer = smp.DistributedOptimizer(optimizer)

train(model, device, train_loader, optimizer)
```

## Pemisahan manual dengan PyTorch
<a name="model-parallel-customize-training-script-pt-16-hvd"></a>

Gunakan manajer [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedOptimizer](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_pytorch.html#smp.DistributedOptimizer)konteks untuk menempatkan modul di perangkat tertentu. Modul apa pun yang tidak ditempatkan dalam `smp.partition` konteks apa pun ditempatkan di. `default_partition` `default_partition`Kebutuhan yang harus `auto_partition` disediakan jika diatur ke`False`. Modul yang dibuat dalam `smp.partition` konteks tertentu ditempatkan pada partisi yang sesuai.

Untuk mempelajari lebih lanjut tentang API pustaka paralelisme model, lihat dokumentasi [API](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smd_model_parallel.html). SageMaker 

```
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchnet.dataset import SplitDataset
from torchvision import datasets

import smdistributed.modelparallel.torch as smp

class GroupedNet(nn.Module):
    def __init__(self):
        super(GroupedNet, self).__init__()
        with smp.partition(0):
            # define child modules on device 0
        with smp.partition(1):
            # define child modules on device 1

    def forward(self, x):
        # define forward pass and return model outputs


# smdistributed: Define smp.step. Return any tensors needed outside.
@smp.step
def train_step(model, data, target):
    output = model(data)
    loss = F.nll_loss(output, target, reduction="mean")
    model.backward(loss)
    return output, loss


def train(model, device, train_loader, optimizer):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        # smdistributed: Move input tensors to the GPU ID used by the current process,
        # based on the set_device call.
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        # Return value, loss_mb is a StepOutput object
        _, loss_mb = train_step(model, data, target)

        # smdistributed: Average the loss across microbatches.
        loss = loss_mb.reduce_mean()

        optimizer.step()

# smdistributed: initialize the backend
smp.init()

# smdistributed: Set the device to the GPU ID used by the current process.
# Input tensors should be transferred to this device.
torch.cuda.set_device(smp.local_rank())
device = torch.device("cuda")

# smdistributed: Download only on a single process per instance.
# When this is not present, the file is corrupted by multiple processes trying
# to download and extract at the same time
dataset = datasets.MNIST("../data", train=True, download=False)

# smdistributed: Shard the dataset based on data-parallel ranks
if smp.dp_size() > 1:
    partitions_dict = {f"{i}": 1 / smp.dp_size() for i in range(smp.dp_size())}
    dataset = SplitDataset(dataset, partitions=partitions_dict)
    dataset.select(f"{smp.dp_rank()}")

# smdistributed: Set drop_last=True to ensure that batch size is always divisible
# by the number of microbatches
train_loader = torch.utils.data.DataLoader(dataset, batch_size=64, drop_last=True)

model = GroupedNet()
optimizer = optim.Adadelta(model.parameters(), lr=4.0)

# smdistributed: Use the DistributedModel container to provide the model
# to be partitioned across different ranks. For the rest of the script,
# the returned DistributedModel object should be used in place of
# the model provided for DistributedModel class instantiation.
model = smp.DistributedModel(model)
optimizer = smp.DistributedOptimizer(optimizer)

train(model, device, train_loader, optimizer)
```

## Pertimbangan-pertimbangan
<a name="model-parallel-pt-considerations"></a>

Saat Anda mengonfigurasi skrip PyTorch pelatihan menggunakan SageMaker pustaka paralelisme model, Anda harus mengetahui hal berikut:
+ Jika Anda menggunakan teknik optimasi yang bergantung pada norma gradien global, misalnya norma gradien dari seluruh model, seperti beberapa varian pengoptimal LAMB atau kliping gradien global, Anda perlu mengumpulkan semua norma di seluruh partisi model untuk kebenaran. Anda dapat menggunakan tipe data dasar komunikasi perpustakaan untuk melakukan hal ini.
+ Semua `torch.Tensor` argumen untuk metode penerusan `nn.Modules` dalam model Anda harus digunakan dalam perhitungan output modul. Dengan kata lain, perpustakaan tidak mendukung kasus di mana ada `torch.Tensor` argumen ke modul di mana output modul tidak bergantung.
+ Argumen untuk `smp.DistributedModel.backward()` panggilan harus bergantung pada semua output model. Dengan kata lain, tidak mungkin ada output dari `smp.DistributedModel.forward` panggilan yang tidak digunakan dalam perhitungan tensor yang dimasukkan ke dalam panggilan. `smp.DistributedModel.backward`
+ Jika ada `torch.cuda.synchronize()` panggilan dalam kode Anda, Anda mungkin perlu menelepon `torch.cuda.set_device(smp.local_rank())` segera sebelum panggilan sinkronisasi. Jika tidak, konteks CUDA yang tidak perlu dapat dibuat di perangkat 0, yang akan menghabiskan memori dengan sia-sia.
+ Karena perpustakaan ditempatkan `nn.Modules` pada perangkat yang berbeda, modul dalam model tidak boleh bergantung pada keadaan global apa pun yang dimodifikasi di dalamnya`smp.step`. Setiap keadaan yang tetap selama pelatihan, atau yang dimodifikasi `smp.step` di luar dengan cara yang terlihat oleh semua proses, diperbolehkan.
+ Anda tidak perlu memindahkan model ke GPU (misalnya, menggunakan`model.to(device)`) saat menggunakan perpustakaan. Jika Anda mencoba memindahkan model ke GPU sebelum model dipartisi (sebelum `smp.step` panggilan pertama), panggilan pindah akan diabaikan. Pustaka secara otomatis memindahkan bagian model yang ditetapkan ke peringkat ke GPU-nya. Setelah pelatihan dengan perpustakaan dimulai, jangan pindahkan model ke CPU dan gunakan, karena tidak akan memiliki parameter yang benar untuk modul yang tidak ditetapkan ke partisi yang dipegang oleh proses. Jika Anda ingin melatih ulang model atau menggunakannya untuk inferensi tanpa perpustakaan setelah dilatih menggunakan pustaka paralelisme model, cara yang disarankan adalah menyimpan model lengkap menggunakan API pos pemeriksaan kami dan memuatnya kembali ke Modul biasa. PyTorch 
+ Jika Anda memiliki daftar modul sehingga output dari satu umpan ke yang lain, mengganti daftar itu dengan `nn.Sequential` dapat secara signifikan meningkatkan kinerja.
+ Pembaruan bobot (`optimizer.step()`) perlu terjadi di luar `smp.step` karena saat itulah seluruh backward pass selesai dan gradien sudah siap. Saat menggunakan model hybrid dengan model dan paralelisme data, pada titik ini, AllReduce gradien juga dijamin selesai.
+ Saat menggunakan library dalam kombinasi dengan paralelisme data, pastikan jumlah batch pada semua data parallel rank sama sehingga AllReduce tidak hang menunggu rank yang tidak berpartisipasi dalam langkah tersebut.
+ Jika Anda meluncurkan pekerjaan pelatihan menggunakan jenis instans ml.p4d (seperti ml.p4d.24xlarge), Anda harus menyetel variabel pemuat data. `num_workers=0` Misalnya, Anda dapat mendefinisikan `DataLoader` sebagai berikut:

  ```
  dataloader = torch.utils.data.DataLoader(
              data,
              batch_size=batch_size,
              num_workers=0,
              pin_memory=True,
              drop_last=True,
              shuffle=shuffle,
          )
  ```
+ Input `smp.step` harus menjadi input model yang dihasilkan oleh. `DataLoader` Ini karena `smp.step` secara internal membagi tensor input di sepanjang dimensi batch dan menyalurkannya. Ini berarti bahwa meneruskan `DataLoader` dirinya ke `smp.step` fungsi untuk menghasilkan input model di dalamnya tidak berfungsi. 

  Misalnya, jika Anda mendefinisikan `DataLoader` sebagai berikut:

  ```
  train_loader = torch.utils.data.DataLoader(dataset, batch_size=64, drop_last=True)
  ```

  Anda harus mengakses input model yang dihasilkan oleh `train_loader` dan meneruskannya ke fungsi yang `smp.step` didekorasi. Jangan `train_loader` langsung lolos ke `smp.step` fungsi.

  ```
  def train(model, device, train_loader, optimizer):
      model.train()
      for batch_idx, (data, target) in enumerate(train_loader):
          ...
          _, loss_mb = train_step(model, data, target)
          ...
  
  @smp.step
  def train_step(model, data, target):
      ...
      return output, loss
  ```
+ Tensor input `smp.step` harus dipindahkan ke perangkat saat ini menggunakan `.to()` API, yang harus dilakukan setelah panggilan. `torch.cuda.set_device(local_rank())`

  Misalnya, Anda dapat mendefinisikan `train` fungsi sebagai berikut. Fungsi ini menambahkan `data` dan `target` ke perangkat saat ini menggunakan `.to()` API sebelum menggunakan tensor input tersebut untuk memanggil. `train_step`

  ```
  def train(model, device, train_loader, optimizer):
      model.train()
      for batch_idx, (data, target) in enumerate(train_loader):
          # smdistributed: Move input tensors to the GPU ID used by the current process,
          # based on the set_device call.
          data, target = data.to(device), target.to(device)
          optimizer.zero_grad()
          # Return value, loss_mb is a StepOutput object
          _, loss_mb = train_step(model, data, target)
  
          # smdistributed: Average the loss across microbatches.
          loss = loss_mb.reduce_mean()
  
          optimizer.step()
  ```

  Tensor input ke fungsi yang `smp.set` didekorasi ini telah dipindahkan ke perangkat saat ini dalam `train` fungsi di atas. Model *tidak* perlu dipindahkan ke perangkat saat ini. Pustaka secara otomatis memindahkan bagian model yang ditetapkan ke peringkat ke GPU-nya.

  ```
  @smp.step
  def train_step(model, data, target):
      output = model(data)
      loss = F.nll_loss(output, target, reduction="mean")
      model.backward(loss)
      return output, loss
  ```

## Fitur kerangka kerja yang tidak didukung
<a name="model-parallel-pt-unsupported-features"></a>

 PyTorch Fitur-fitur berikut tidak didukung oleh pustaka SageMaker paralelisme model:
+ Jika Anda menggunakan paralelisme data dengan [PyTorch DDP](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html) asli, modul [https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html](https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html)pembungkus tidak didukung oleh perpustakaan. Pustaka secara internal mengelola integrasi dengan PyTorch DDP, termasuk siaran parameter dan gradien. AllReduce Saat menggunakan perpustakaan, buffer modul hanya disiarkan sekali pada awal pelatihan. Jika model Anda memiliki buffer modul yang perlu disinkronkan di seluruh grup paralel data pada setiap langkah, Anda dapat melakukannya melalui `torch.distributed` API, menggunakan grup proses yang dapat diperoleh melalui. `smp.get_dp_process_group()`
+ Untuk pelatihan presisi campuran, `apex.amp` modul tidak didukung. Cara yang disarankan untuk menggunakan perpustakaan dengan presisi campuran otomatis adalah dengan menggunakan`torch.cuda.amp`, dengan pengecualian menggunakan `smp.amp.GradScaler` alih-alih implementasi dalam obor.
+ `torch.jit.ScriptModules`atau `ScriptFunctions` tidak didukung oleh`smp.DistributedModel`.
+ `apex`:`FusedLayerNorm`,`FusedAdam`,`FusedLAMB`, dan `FusedNovoGrad` dari `apex` tidak didukung. Anda dapat menggunakan implementasi perpustakaan ini melalui `smp.optimizers` dan `smp.nn` APIs sebagai gantinya.