

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

# Langkah 1: Ubah Skrip Pelatihan Anda Sendiri Menggunakan SageMaker Perpustakaan Paralel Model Terdistribusi
<a name="model-parallel-customize-training-script"></a>

Gunakan bagian ini untuk mempelajari cara menyesuaikan skrip pelatihan Anda untuk menggunakan fitur inti dari perpustakaan paralelisme model Amazon SageMaker AI. *Untuk menggunakan fungsi dan parameter API khusus perpustakaan, kami sarankan Anda menggunakan dokumentasi ini bersama [pustaka SageMaker paralel](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smd_model_parallel.html) model APIs dalam dokumentasi Python SageMaker SDK.*

Contoh skrip pelatihan yang disediakan di bagian ini disederhanakan dan dirancang untuk menyoroti perubahan yang diperlukan yang harus Anda lakukan untuk menggunakan perpustakaan. Untuk end-to-end contoh buku catatan yang dapat dijalankan yang menunjukkan cara menggunakan skrip TensorFlow atau PyTorch pelatihan dengan pustaka paralelisme SageMaker model, lihat. [Contoh perpustakaan paralelisme model Amazon SageMaker AI v2](distributed-model-parallel-v2-examples.md)

**Topics**
+ [Pisahkan model skrip pelatihan Anda menggunakan pustaka paralelisme SageMaker model](#model-parallel-model-splitting-using-smp-lib)
+ [Memodifikasi skrip TensorFlow pelatihan](model-parallel-customize-training-script-tf.md)
+ [Memodifikasi Skrip PyTorch Pelatihan](model-parallel-customize-training-script-pt.md)

## Pisahkan model skrip pelatihan Anda menggunakan pustaka paralelisme SageMaker model
<a name="model-parallel-model-splitting-using-smp-lib"></a>

Ada dua cara untuk memodifikasi skrip pelatihan Anda untuk mengatur pemisahan model: pemisahan otomatis atau pemisahan manual.

### Pemisahan model otomatis
<a name="model-parallel-automated-model-splitting"></a>

Saat Anda menggunakan SageMaker pustaka paralelisme model, Anda dapat memanfaatkan *pemisahan model otomatis*, juga disebut sebagai partisi model *otomatis*. Pustaka menggunakan algoritma partisi yang menyeimbangkan memori, meminimalkan komunikasi antar perangkat, dan mengoptimalkan kinerja. Anda dapat mengonfigurasi algoritma partisi otomatis untuk mengoptimalkan kecepatan atau memori. 

Atau, Anda dapat menggunakan pemisahan model manual. Kami merekomendasikan pemisahan model otomatis, kecuali jika Anda sangat akrab dengan arsitektur model dan memiliki ide bagus tentang cara mempartisi model Anda secara efisien.

#### Cara kerjanya
<a name="model-parallel-automated-model-splitting-how-it-works"></a>

Partisi otomatis terjadi selama langkah pelatihan pertama, ketika fungsi `smp.step` -decorated pertama kali dipanggil. Selama panggilan ini, perpustakaan pertama-tama membuat versi model pada RAM CPU (untuk menghindari keterbatasan memori GPU), dan kemudian menganalisis grafik model dan membuat keputusan partisi. Berdasarkan keputusan ini, setiap partisi model dimuat pada GPU, dan baru kemudian langkah pertama dijalankan. Karena langkah-langkah analisis dan partisi ini, langkah pelatihan pertama mungkin memakan waktu lebih lama. 

Dalam kedua kerangka kerja, perpustakaan mengelola komunikasi antar perangkat melalui backend sendiri, yang dioptimalkan untuk AWS infrastruktur.

Desain partisi otomatis menyesuaikan dengan karakteristik kerangka kerja, dan perpustakaan melakukan partisi pada tingkat granularitas yang lebih alami di setiap kerangka kerja. Misalnya, di TensorFlow, setiap operasi tertentu dapat ditugaskan ke perangkat yang berbeda, sedangkan pada PyTorch, penugasan dilakukan pada tingkat modul, di mana setiap modul terdiri dari beberapa operasi. Bagian berikut mengulas spesifikasi desain di setiap kerangka kerja.

##### Pemisahan model otomatis dengan PyTorch
<a name="model-parallel-auto-model-split-pt"></a>

Selama langkah pelatihan pertama, perpustakaan paralelisme model secara internal menjalankan langkah penelusuran yang dimaksudkan untuk membangun grafik model dan menentukan bentuk tensor dan parameter. Setelah langkah penelusuran ini, perpustakaan membangun pohon, yang terdiri dari `nn.Module` objek bersarang dalam model, serta data tambahan yang dikumpulkan dari penelusuran, seperti jumlah yang disimpan`nn.Parameters`, dan waktu eksekusi untuk masing-masing. `nn.Module` 

Selanjutnya, perpustakaan melintasi pohon ini dari root dan menjalankan algoritma partisi yang menetapkan masing-masing `nn.Module` ke perangkat, yang menyeimbangkan beban komputasi (diukur dengan waktu eksekusi modul) dan penggunaan memori (diukur dengan total ukuran dan aktivasi yang disimpan). `nn.Parameter` Jika beberapa `nn.Modules` berbagi yang sama`nn.Parameter`, maka modul ini ditempatkan pada perangkat yang sama untuk menghindari mempertahankan beberapa versi dari parameter yang sama. Setelah keputusan partisi dibuat, modul dan bobot yang ditetapkan dimuat ke perangkat mereka.

Untuk petunjuk tentang cara mendaftarkan `smp.step` dekorator ke skrip PyTorch pelatihan Anda, lihat[Pemisahan otomatis dengan PyTorch](model-parallel-customize-training-script-pt.md#model-parallel-customize-training-script-pt-16).

##### Pemisahan model otomatis dengan TensorFlow
<a name="model-parallel-auto-model-split-tf"></a>

Pustaka paralelisme model menganalisis ukuran variabel yang dapat dilatih dan struktur grafik, dan secara internal menggunakan algoritma partisi grafik. Algoritma ini hadir dengan penugasan perangkat untuk setiap operasi, dengan tujuan meminimalkan jumlah komunikasi yang dibutuhkan di seluruh perangkat, tunduk pada dua kendala: 
+ Menyeimbangkan jumlah variabel yang disimpan di setiap perangkat
+ Menyeimbangkan jumlah operasi yang dijalankan di setiap perangkat

Jika Anda menentukan `speed` for `optimize` (dalam parameter paralelisme model di SDK Python), pustaka mencoba menyeimbangkan jumlah operasi dan `tf.Variable` objek di setiap perangkat. Jika tidak, ia mencoba menyeimbangkan ukuran total`tf.Variables`.

Setelah keputusan partisi dibuat, pustaka akan membuat representasi serial dari subgraf yang perlu dijalankan oleh setiap perangkat dan mengimpornya ke setiap perangkat. Saat mempartisi, perpustakaan menempatkan operasi yang menggunakan yang sama `tf.Variable` dan operasi yang merupakan bagian dari lapisan Keras yang sama ke perangkat yang sama. Ini juga menghormati kendala kolokasi yang diberlakukan oleh. TensorFlow Ini berarti bahwa, misalnya, jika ada dua lapisan Keras yang berbagi a`tf.Variable`, maka semua operasi yang merupakan bagian dari lapisan ini ditempatkan pada satu perangkat.

Untuk petunjuk tentang cara mendaftarkan `smp.step` dekorator ke skrip PyTorch pelatihan Anda, lihat[Pemisahan otomatis dengan TensorFlow](model-parallel-customize-training-script-tf.md#model-parallel-customize-training-script-tf-23).

##### Perbandingan pemisahan model otomatis antar kerangka kerja
<a name="model-parallel-auto-model-split-comparison"></a>

Dalam TensorFlow, unit dasar komputasi adalah a`tf.Operation`, dan TensorFlow mewakili model sebagai grafik asiklik terarah (DAG) dari `tf.Operation` s, dan oleh karena itu perpustakaan paralelisme model mempartisi DAG ini sehingga setiap node masuk ke satu perangkat. Yang terpenting, `tf.Operation` objek cukup kaya dengan atribut yang dapat disesuaikan, dan bersifat universal dalam arti bahwa setiap model dijamin terdiri dari grafik objek tersebut. 

PyTorch di sisi lain, tidak memiliki gagasan operasi yang setara yang cukup kaya dan universal. Unit komputasi terdekat PyTorch yang memiliki karakteristik ini adalah`nn.Module`, yang berada pada tingkat granularitas yang jauh lebih tinggi, dan inilah mengapa perpustakaan melakukan partisi pada tingkat ini di. PyTorch

### Pemisahan Model Manual
<a name="model-parallel-manual-model-splitting"></a>

Jika Anda ingin menentukan secara manual cara mempartisi model Anda di seluruh perangkat, gunakan pengelola `smp.partition` konteks. Untuk petunjuk tentang cara mengatur manajer konteks untuk partisi manual, lihat halaman berikut.
+ [Pemisahan manual dengan TensorFlow](model-parallel-customize-training-script-tf.md#model-parallel-customize-training-script-tf-manual)
+ [Pemisahan manual dengan PyTorch](model-parallel-customize-training-script-pt.md#model-parallel-customize-training-script-pt-16-hvd)

Untuk menggunakan opsi ini setelah melakukan modifikasi, pada Langkah 2, Anda harus mengatur `auto_partition` ke`False`, dan menentukan kelas estimator kerangka kerja dari SageMaker Python SDK. `default_partition` Setiap operasi yang tidak secara eksplisit ditempatkan pada partisi melalui manajer `smp.partition` konteks dijalankan pada file. `default_partition` Dalam hal ini, logika pemisahan otomatis dilewati, dan setiap operasi ditempatkan berdasarkan spesifikasi Anda. Berdasarkan struktur grafik yang dihasilkan, pustaka paralelisme model membuat jadwal eksekusi pipelined secara otomatis.

# Memodifikasi skrip TensorFlow pelatihan
<a name="model-parallel-customize-training-script-tf"></a>

Di bagian ini, Anda mempelajari cara memodifikasi skrip TensorFlow pelatihan untuk mengonfigurasi pustaka paralelisme SageMaker model untuk partisi otomatis dan partisi manual. Pemilihan contoh ini juga mencakup contoh yang terintegrasi dengan Horovod untuk model hibrida dan paralelisme data.

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

Modifikasi yang diperlukan yang harus Anda lakukan pada skrip pelatihan Anda untuk menggunakan perpustakaan tercantum di dalamnya[Pemisahan otomatis dengan TensorFlow](#model-parallel-customize-training-script-tf-23).

Untuk mempelajari cara memodifikasi skrip pelatihan Anda untuk menggunakan model hibrida dan paralelisme data dengan Horovod, lihat. [Pemisahan otomatis dengan TensorFlow dan Horovod untuk model hibrida dan paralelisme data](#model-parallel-customize-training-script-tf-2.3)

Jika Anda ingin menggunakan partisi manual, tinjau juga. [Pemisahan manual dengan TensorFlow](#model-parallel-customize-training-script-tf-manual) 

Topik berikut menunjukkan contoh skrip pelatihan yang dapat Anda gunakan untuk mengonfigurasi SageMaker pustaka paralelisme model untuk model partisi otomatis dan partisi manual. TensorFlow 

**catatan**  
Partisi otomatis diaktifkan secara default. Kecuali ditentukan lain, skrip contoh menggunakan partisi otomatis.

**Topics**
+ [Pemisahan otomatis dengan TensorFlow](#model-parallel-customize-training-script-tf-23)
+ [Pemisahan otomatis dengan TensorFlow dan Horovod untuk model hibrida dan paralelisme data](#model-parallel-customize-training-script-tf-2.3)
+ [Pemisahan manual dengan TensorFlow](#model-parallel-customize-training-script-tf-manual)
+ [Fitur kerangka kerja yang tidak didukung](#model-parallel-tf-unsupported-features)

## Pemisahan otomatis dengan TensorFlow
<a name="model-parallel-customize-training-script-tf-23"></a>

Perubahan skrip pelatihan berikut diperlukan untuk menjalankan TensorFlow model 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. Mendefinisikan model Keras dengan mewarisi dari [https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_tensorflow.html](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_tensorflow.html)bukan kelas Model Keras. Kembalikan output model dari metode panggilan `smp.DistributedModel` objek. Perhatikan bahwa setiap tensor yang dikembalikan dari metode panggilan akan disiarkan di seluruh perangkat paralel model, yang menimbulkan overhead komunikasi, jadi tensor apa pun yang tidak diperlukan di luar metode panggilan (seperti aktivasi perantara) tidak boleh dikembalikan.

1. Ditetapkan `drop_remainder=True` dalam `tf.Dataset.batch()` metode. Ini untuk memastikan bahwa ukuran batch selalu habis dibagi dengan jumlah microbatch.

1. Benih operasi acak dalam pipa data menggunakan`smp.dp_rank()`, misalnya, `shuffle(ds, seed=smp.dp_rank())` untuk memastikan konsistensi sampel data di seluruh GPUs yang memegang partisi model yang berbeda.

1. Letakkan logika maju dan mundur dalam fungsi langkah dan hiasi dengan`smp.step`.

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` [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)Fungsi harus memiliki nilai kembali yang tergantung pada output dari`smp.DistributedModel`.

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)

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 

Skrip Python berikut adalah contoh skrip pelatihan setelah perubahan dilakukan.

```
import tensorflow as tf

# smdistributed: Import TF2.x API
import smdistributed.modelparallel.tensorflow as smp

# smdistributed: Initialize
smp.init()

# Download and load MNIST dataset.
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data(
    "MNIST-data-%d" % smp.rank()
)
x_train, x_test = x_train / 255.0, x_test / 255.0

# Add a channels dimension
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

# smdistributed: If needed, seed the shuffle with smp.dp_rank(), and drop_remainder
# in batching to make sure batch size is always divisible by number of microbatches
train_ds = (
    tf.data.Dataset.from_tensor_slices((x_train, y_train))
    .shuffle(10000, seed=smp.dp_rank())
    .batch(256, drop_remainder=True)
)

# smdistributed: Define smp.DistributedModel the same way as Keras sub-classing API 
class MyModel(smp.DistributedModel):
    def __init__(self):
        super(MyModel, self).__init__()
        # define layers

    def call(self, x, training=None):
        # define forward pass and return the model output

model = MyModel()

loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam()
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name="train_accuracy")

# smdistributed: Define smp.step. Return any tensors needed outside
@smp.step
def get_grads(images, labels):
    predictions = model(images, training=True)
    loss = loss_object(labels, predictions)

    grads = optimizer.get_gradients(loss, model.trainable_variables)
    return grads, loss, predictions


@tf.function
def train_step(images, labels):
    gradients, loss, predictions = get_grads(images, labels)

    # smdistributed: Accumulate the gradients across microbatches
    gradients = [g.accumulate() for g in gradients]
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    # smdistributed: Merge predictions and average losses across microbatches
    train_accuracy(labels, predictions.merge())
    return loss.reduce_mean()


for epoch in range(5):
    # Reset the metrics at the start of the next epoch
    train_accuracy.reset_states()
    for images, labels in train_ds:
        loss = train_step(images, labels)
    accuracy = train_accuracy.result()
```

Jika Anda selesai mempersiapkan skrip pelatihan Anda, lanjutkan ke[Langkah 2: Luncurkan Training Job Menggunakan SageMaker Python SDK](model-parallel-sm-sdk.md). Jika Anda ingin menjalankan model hybrid dan pekerjaan pelatihan paralel data, lanjutkan ke bagian berikutnya.

## Pemisahan otomatis dengan TensorFlow dan Horovod untuk model hibrida dan paralelisme data
<a name="model-parallel-customize-training-script-tf-2.3"></a>

Anda dapat menggunakan perpustakaan paralelisme SageMaker model dengan Horovod untuk model hibrida dan paralelisme data. Untuk membaca lebih lanjut tentang bagaimana perpustakaan membagi model untuk paralelisme hibrida, lihat. [Paralelisme pipa (tersedia untuk PyTorch dan) TensorFlow](model-parallel-intro.md#model-parallel-intro-pp)

Pada langkah ini, kami fokus pada cara memodifikasi skrip pelatihan Anda untuk mengadaptasi perpustakaan paralelisme SageMaker model.

Untuk mengatur skrip pelatihan dengan benar untuk mengambil konfigurasi paralelisme hibrida yang akan Anda atur[Langkah 2: Luncurkan Training Job Menggunakan SageMaker Python SDK](model-parallel-sm-sdk.md), gunakan fungsi pembantu perpustakaan, `smp.dp_rank()` dan`smp.mp_rank()`, yang secara otomatis mendeteksi peringkat paralel data dan peringkat paralel model masing-masing. 

Untuk menemukan semua primitif MPI yang didukung perpustakaan, lihat [Dasar MPI](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/v1.2.0/smd_model_parallel_common_api.html#mpi-basics) dalam dokumentasi Python SageMaker SDK. 

Perubahan yang diperlukan dalam skrip adalah:
+ Menambahkan `hvd.allreduce`
+ Variabel penyiaran setelah batch pertama, seperti yang dipersyaratkan oleh Horovod
+ Operasi and/or sharding pengocokan penyemaian benih dalam pipa data dengan. `smp.dp_rank()`

**catatan**  
Saat Anda menggunakan Horovod, Anda tidak boleh langsung memanggil skrip `hvd.init` pelatihan Anda. Sebagai gantinya, Anda harus mengatur `"horovod"` ke `True` dalam parameter SDK SageMaker `modelparallel` Python di. [Langkah 2: Luncurkan Training Job Menggunakan SageMaker Python SDK](model-parallel-sm-sdk.md) Hal ini memungkinkan perpustakaan untuk menginisialisasi Horovod secara internal berdasarkan penetapan perangkat partisi model. Memanggil `hvd.init()` langsung dalam skrip pelatihan Anda dapat menyebabkan masalah.

**catatan**  
Menggunakan `hvd.DistributedOptimizer` API secara langsung di skrip pelatihan Anda dapat mengakibatkan kinerja dan kecepatan pelatihan yang buruk, karena API secara implisit menempatkan `AllReduce` operasi di dalamnya. `smp.step` Kami menyarankan Anda untuk menggunakan perpustakaan paralelisme model dengan Horovod dengan langsung memanggil `hvd.allreduce` setelah memanggil `accumulate()` atau `reduce_mean()` pada gradien yang dikembalikan dari`smp.step`, seperti yang akan ditunjukkan pada contoh berikut.

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 tensorflow as tf
import horovod.tensorflow as hvd

# smdistributed: Import TF2.x API 
import smdistributed.modelparallel.tensorflow as smp

# smdistributed: Initialize
smp.init()

# Download and load MNIST dataset.
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data(
    "MNIST-data-%d" % smp.rank()
)
x_train, x_test = x_train / 255.0, x_test / 255.0

# Add a channels dimension
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

# smdistributed: Seed the shuffle with smp.dp_rank(), and drop_remainder
# in batching to make sure batch size is always divisible by number of microbatches
train_ds = (
    tf.data.Dataset.from_tensor_slices((x_train, y_train))
    .shuffle(10000, seed=smp.dp_rank())
    .batch(256, drop_remainder=True)
)

# smdistributed: Define smp.DistributedModel the same way as Keras sub-classing API 
class MyModel(smp.DistributedModel):
    def __init__(self):
        super(MyModel, self).__init__()
        # define layers

    def call(self, x, training=None):
        # define forward pass and return model outputs


model = MyModel()

loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam()
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name="train_accuracy")

# smdistributed: Define smp.step. Return any tensors needed outside
@smp.step
def get_grads(images, labels):
    predictions = model(images, training=True)
    loss = loss_object(labels, predictions)

    grads = optimizer.get_gradients(loss, model.trainable_variables)
    return grads, loss, predictions


@tf.function
def train_step(images, labels, first_batch):
    gradients, loss, predictions = get_grads(images, labels)

    # smdistributed: Accumulate the gradients across microbatches
    # Horovod: AllReduce the accumulated gradients
    gradients = [hvd.allreduce(g.accumulate()) for g in gradients]
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    # Horovod: Broadcast the variables after first batch 
    if first_batch:
        hvd.broadcast_variables(model.variables, root_rank=0)
        hvd.broadcast_variables(optimizer.variables(), root_rank=0)

    # smdistributed: Merge predictions across microbatches
    train_accuracy(labels, predictions.merge())
    return loss.reduce_mean()


for epoch in range(5):
    # Reset the metrics at the start of the next epoch
    train_accuracy.reset_states()

    for batch, (images, labels) in enumerate(train_ds):
        loss = train_step(images, labels, tf.constant(batch == 0))
```

## Pemisahan manual dengan TensorFlow
<a name="model-parallel-customize-training-script-tf-manual"></a>

Gunakan manajer `smp.partition` konteks untuk menempatkan operasi di partisi tertentu. Setiap operasi yang tidak ditempatkan dalam `smp.partition` konteks apa pun ditempatkan di. `default_partition` 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 tensorflow as tf

# smdistributed: Import TF2.x API.
import smdistributed.modelparallel.tensorflow as smp

# smdistributed: Initialize
smp.init()

# Download and load MNIST dataset.
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data(
    "MNIST-data-%d" % smp.rank()
)
x_train, x_test = x_train / 255.0, x_test / 255.0

# Add a channels dimension
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

# smdistributed: If needed, seed the shuffle with smp.dp_rank(), and drop_remainder
# in batching to make sure batch size is always divisible by number of microbatches.
train_ds = (
    tf.data.Dataset.from_tensor_slices((x_train, y_train))
    .shuffle(10000, seed=smp.dp_rank())
    .batch(256, drop_remainder=True)
)

# smdistributed: Define smp.DistributedModel the same way as Keras sub-classing API.
class MyModel(smp.DistributedModel):
    def __init__(self):
         # define layers

    def call(self, x):
        with smp.partition(0):
            x = self.layer0(x)
        with smp.partition(1):
            return self.layer1(x)


model = MyModel()

loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam()
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name="train_accuracy")

# smdistributed: Define smp.step. Return any tensors needed outside
@smp.step
def get_grads(images, labels):
    predictions = model(images, training=True)
    loss = loss_object(labels, predictions)

    grads = optimizer.get_gradients(loss, model.trainable_variables)
    return grads, loss, predictions


@tf.function
def train_step(images, labels):
    gradients, loss, predictions = get_grads(images, labels)

    # smdistributed: Accumulate the gradients across microbatches
    gradients = [g.accumulate() for g in gradients]
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    # smdistributed: Merge predictions and average losses across microbatches
    train_accuracy(labels, predictions.merge())
    return loss.reduce_mean()


for epoch in range(5):
    # Reset the metrics at the start of the next epoch
    train_accuracy.reset_states()
    for images, labels in train_ds:
        loss = train_step(images, labels)
    accuracy = train_accuracy.result()
```

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

 TensorFlow Fitur-fitur berikut tidak didukung oleh pustaka:
+ `tf.GradientTape()`saat ini tidak didukung. Anda dapat menggunakan `Optimizer.get_gradients()` atau `Optimizer.compute_gradients()` sebagai gantinya untuk menghitung gradien.
+ `tf.train.Checkpoint.restore()`API saat ini tidak didukung. Untuk checkpointing, gunakan `smp.CheckpointManager` sebagai gantinya, yang menyediakan API dan fungsionalitas yang sama. Perhatikan bahwa pemulihan pos pemeriksaan dengan `smp.CheckpointManager` harus dilakukan setelah langkah pertama.

# 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.