

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 教學
<a name="tutorials"></a>

以下是如何使用 Deep Learning AMI 搭配 Conda 軟體的教學課程。

**Topics**
+ [啟用架構](activating.md)
+ [使用 Elastic Fabric Adapter 的分散式訓練](tutorial-efa.md)
+ [GPU 監控和最佳化](tutorial-gpu.md)
+ [具有 DLAMI AWS 的 Inferentia Chip](tutorial-inferentia.md)
+ [ARM64 DLAMI](tutorial-arm64.md)
+ [Inference](tutorial-inference.md)
+ [模型服務](model-serving.md)

# 啟用架構
<a name="activating"></a>

以下是安裝在 Deep Learning AMI with Conda 上的深度學習架構。按一下某個架構，以了解如何啟用。

**Topics**
+ [PyTorch](tutorial-pytorch.md)
+ [TensorFlow 2](tutorial-tensorflow-2.md)

# PyTorch
<a name="tutorial-pytorch"></a>

## 啟用 PyTorch
<a name="tutorial-pytorch-overview"></a>

發行穩定的架構 Conda 套件時，會進行測試並預先安裝在 DLAMI 上。如果您想要執行最新、未經測試的每夜組建，您可以手動[安裝 PyTorch 的每夜組建 (實驗性)](#tutorial-pytorch-install)。

若要啟用目前安裝的架構，請遵循使用 Conda 的深度學習 AMI 上的這些指示。

對於使用 CUDA 和 MKL-DNN 的 Python 3 上的 PyTorch，請執行此命令：

```
$ source activate pytorch_p310
```

啟動 iPython 終端機。

```
(pytorch_p310)$ ipython
```

執行快速 PyTorch 程式。

```
import torch
x = torch.rand(5, 3)
print(x)
print(x.size())
y = torch.rand(5, 3)
print(torch.add(x, y))
```

您應該會看到列印初始隨機陣列、接著是其大小，然後新增另一個隨機陣列。

## 安裝 PyTorch 的每夜組建 (實驗性)
<a name="tutorial-pytorch-install"></a>

**如何從每夜組建安裝 PyTorch**

您可以使用 Conda 在深度學習 AMI 上安裝最新的 PyTorch 組建到其中一個或兩個 PyTorch Conda 環境中。

1. 
   + (適用於 Python 3 的選項) - 啟用 Python 3 PyTorch 環境：

     ```
     $ source activate pytorch_p310
     ```

1. 其餘步驟假設您使用的是 `pytorch_p310` 環境。移除目前安裝的 PyTorch：

   ```
   (pytorch_p310)$ pip uninstall torch
   ```

1. 
   + (GPU 執行個體的選項） - 使用 CUDA.0 安裝 PyTorch 的最新每夜組建：

     ```
     (pytorch_p310)$ pip install torch_nightly -f https://download.pytorch.org/whl/nightly/cu100/torch_nightly.html
     ```
   + (適用於 CPU 執行個體的選項) – 安裝適用於無 GPU 之執行個體的最新 PyTorch 每夜組建：

     ```
     (pytorch_p310)$ pip install torch_nightly -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html
     ```

1. 為了確認您是否成功安裝最新的每夜組建，請啟動 IPython 終端機並檢查 PyTorch 版本。

   ```
   (pytorch_p310)$ ipython
   ```

   ```
   import torch
   print (torch.__version__)
   ```

   輸出應該會列印類似於 `1.0.0.dev20180922` 的內容

1. 若要確認 PyTorch 每夜組建可搭配 MNIST 範例正常運作，您可以從 PyTorch 範例儲存庫執行測試指令碼：

   ```
   (pytorch_p310)$ cd ~
   (pytorch_p310)$ git clone https://github.com/pytorch/examples.git pytorch_examples
   (pytorch_p310)$ cd pytorch_examples/mnist
   (pytorch_p310)$ python main.py || exit 1
   ```

## 其他教學
<a name="tutorial-pytorch-more"></a>

如需進一步的教學課程和範例，請參閱架構的官方文件、[PyTorch 文件](http://pytorch.org/docs/master/)和 [PyTorch](http://pytorch.org) 網站。

# TensorFlow 2
<a name="tutorial-tensorflow-2"></a>

本教學課程示範如何在執行具有 Conda 的深度學習 AMI (Conda 上的 DLAMI) 的執行個體上啟用 TensorFlow 2，並執行 TensorFlow 2 程式。

發行穩定的架構 Conda 套件時，會進行測試並預先安裝在 DLAMI 上。

## 啟用 TensorFlow 2
<a name="tutorial-tensorflow-2-overview"></a>

**使用 Conda 在 DLAMI 上執行 TensorFlow**

1. 若要啟用 TensorFlow 2，請使用 Conda 開啟 DLAMI 的 Amazon Elastic Compute Cloud (Amazon EC2) 執行個體。

1. 對於使用 CUDA 10.1 和 MKL-DNN 的 Python 3 上的 TensorFlow 2 和 Keras 2，請執行此命令：

   ```
   $ source activate tensorflow2_p310
   ```

1. 啟動 iPython 終端機：

   ```
   (tensorflow2_p310)$ ipython
   ```

1. 執行 TensorFlow 2 程式，以驗證其運作正常：

   ```
   import tensorflow as tf
   hello = tf.constant('Hello, TensorFlow!')
   tf.print(hello)
   ```

   `Hello, TensorFlow!` 應該會出現在您的畫面上。

## 其他教學
<a name="tutorial-tensorflow-2-more"></a>

如需更多教學課程和範例，請參閱 TensorFlow [Python API 的 TensorFlow ](https://www.tensorflow.org/api_docs/python/) 文件，或參閱 [TensorFlow](https://www.tensorflow.org) 網站。

# 使用 Elastic Fabric Adapter 的分散式訓練
<a name="tutorial-efa"></a>

[Elastic Fabric Adapter](https://aws.amazon.com/hpc/efa/) (EFA) 是一種網路裝置，您可以連接到 DLAMI 執行個體，以加速高效能運算 (HPC) 應用程式。EFA 可讓您透過 AWS 雲端提供的可擴展性、彈性和彈性，實現現場部署 HPC 叢集的應用程式效能。

下列主題說明如何開始使用 EFA 搭配 DLAMI。

**注意**  
從此[基本 GPU DLAMI 清單中選擇您的 DLAMI](appendix-ami-release-notes.md#appendix-ami-release-notes-base)

**Topics**
+ [使用 EFA 啟動 AWS 深度學習 AMIs 執行個體](tutorial-efa-launching.md)
+ [在 DLAMI 上使用 EFA](tutorial-efa-using.md)

# 使用 EFA 啟動 AWS 深度學習 AMIs 執行個體
<a name="tutorial-efa-launching"></a>

最新的 Base DLAMI 已準備好與 EFA 搭配使用，並隨附 GPU 執行個體所需的驅動程式、核心模組、libfabric、Openmpi 和 [NCCL OFI 外掛程式](https://github.com/aws/aws-ofi-nccl/tree/aws)。

您可以在版本[備註中找到基礎 DLAMI 支援的 CUDA 版本](appendix-ami-release-notes.md#appendix-ami-release-notes-base)。

請注意：
+ 在 EFA `mpirun`上使用 執行 NCCL 應用程式時，您必須將 EFA 支援安裝的完整路徑指定為：

  ```
  /opt/amazon/openmpi/bin/mpirun <command>  
  ```
+ 若要讓您的應用程式能夠使用 EFA，請新增 `FI_PROVIDER="efa"` 至 `mpirun` 命令，如 [在 DLAMI 上使用 EFA](tutorial-efa-using.md) 中所示。

**Topics**
+ [準備啟用 EFA 的安全群組](#tutorial-efa-security-group)
+ [啟動您的執行個體](#tutorial-efa-launch)
+ [驗證 EFA 附件](#tutorial-efa-verify-attachment)

## 準備啟用 EFA 的安全群組
<a name="tutorial-efa-security-group"></a>

EFA 需要安全群組，允許所有進出安全群組本身的傳入和傳出流量。如需詳細資訊，請參閱 [EFA 文件](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa-start.html#efa-start-security)。

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格中，選擇 **Security Groups** (安全群組)，然後選擇 **Create Security Group** (建立安全群組)。

1. 在 **Create Security Group** (建立安全群組) 視窗中，執行下列動作：
   + 對於 **Security group name** (安全群組名稱)，輸入安全群組的描述性名稱，例如 `EFA-enabled security group`。
   + (選用) 對於 **Description** (描述)，輸入安全群組的簡短描述。
   + 對於 **VPC**，選取您打算讓具備 EFA 功能的執行個體在其中啟動的 VPC。
   + 選擇**建立**。

1. 選取您建立的安全群組，在 **Description** (描述) 索引標籤上，複製 **Group ID** (群組 ID)。

1. 在**傳入**和**傳出**索引標籤上，執行下列動作：
   + 選擇 **Edit** (編輯)。
   + 針對 **Type (類型)**，選擇 **All traffic (所有流量)**。
   + 對於 **Source (資源)**，選擇 **Custom (自訂)**。
   + 將您複製的安全群組 ID 貼到欄位中。
   + 選擇**儲存**。

1. 參照 [授權 Linux 執行個體的傳入流量](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html)來啟用傳入流量。如果您略過此步驟，將無法與 DLAMI 執行個體通訊。

## 啟動您的執行個體
<a name="tutorial-efa-launch"></a>

上的 EFA AWS 深度學習 AMIs 目前支援下列執行個體類型和作業系統：
+  P3dn：Amazon Linux 2、Ubuntu 20.04
+  P4d, P4de：Amazon Linux 2、Amazon Linux 2023、Ubuntu 20.04、Ubuntu 22.04
+  P5, P5e, P5en：Amazon Linux 2、Amazon Linux 2023、Ubuntu 20.04、Ubuntu 22.04

下一節說明如何啟動已啟用 EFA 的 DLAMI 執行個體。如需啟動啟用 EFA 執行個體的詳細資訊，請參閱[在叢集置放群組中啟動啟用 EFA 的執行個體](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa-start.html#efa-start-instances)。

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 選擇**啟動執行個體**。

1. 在**選擇 AMI** 頁面上，選取 DLAMI [版本備註頁面上找到的支援 DLAMI](https://docs.aws.amazon.com/dlami/latest/devguide/appendix-ami-release-notes) 

1. 在**選擇執行個體類型**頁面上，選取下列其中一個支援的執行個體類型，然後選擇**下一步：設定執行個體詳細資訊。**如需支援的執行個體清單，請參閱此連結：[開始使用 EFA 和 MPI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa-start.html) 

1. 在 **Configure Instance Details (設定執行個體詳細資訊)** 頁面上，執行下列操作：
   + 對於 **Number of instances (執行個體的數目)**，輸入要啟動的具備 EFA 功能的執行個體數。
   + 對於 **Network (網路)** 和 **Subnet (子網)**，選取要在其中啟動執行個體的 VPC 和子網。
   + 【選用】 針對**置放群組**，選取**將執行個體新增至置放群組**。為獲得最佳效能，請在置放群組內啟動執行個體。
   + 【選用】 對於**置放群組名稱**，選取**新增至新的置放群組**，輸入置放群組的描述性名稱，然後對於**置放群組策略**，選取**叢集**。
   + 請務必在此頁面上啟用**「彈性布料轉接器」**。如果停用此選項，請將子網路變更為支援您所選執行個體類型的子網路。
   + 在 **Network Interfaces** (網路介面) 區段中，針對裝置 **eth0**，選擇 **New network interface** (新網路介面)。您可以選擇性指定一個主要 IPv4 地址，以及一或多個次要 IPv4 地址。如果您在有相關聯 IPv6 CIDR 區塊的子網中啟動執行個體，您可以選擇性指定一個主要 IPv6 地址，以及一或多個次要 IPv6 地址。
   + 選擇 **Next: Add Storage (下一步：新增儲存體)**。

1. 在 **Add Storage (新增儲存體)** 頁面上，除了 AMI 指定的磁碟區 (例如根設備磁碟區)，指定要連接到執行個體的磁碟區，然後選擇 **Next: Add Tags (下一步：新增標籤)**。

1. 在 **Add Tags (新增標籤)** 頁面上，為執行個體指定標籤 (例如使用者易記的名稱)，然後選擇 **Next: Configure Security Group (下一步：設定安全群組)**。

1. 在**設定安全群組**頁面上，針對**指派安全群組**，選取**選取現有的安全群組**，然後選取您先前建立的安全群組**。**

1. 選擇 **Review and Launch** (檢閱和啟動)。

1. 在 **Review Instance Launch (檢閱執行個體啟動)** 頁面上，檢閱設定，然後選擇 **Launch (啟動)**，以選擇金鑰對並啟動執行個體。

## 驗證 EFA 附件
<a name="tutorial-efa-verify-attachment"></a>

### 從主控台
<a name="tutorial-efa-verify-attachment-console"></a>

啟動執行個體之後，請在 AWS 主控台中檢查執行個體詳細資訊。若要執行此操作，在 EC2 主控台中選取執行個體，然後查看頁面下方窗格中的 [Description (描述)] 索引標籤。尋找參數 “網路界面：eth0”，然後按一下 eth0 開啟一個彈出式畫面。確定已啟用「Elastic Fabric Adapter」。

如果未啟用 EFA，您可以透過下列任一方式修正此問題：
+ 終止 EC2 執行個體並按照相同的步驟啟動新的執行個體。確定已連接 EFA。
+ 將 EFA 連接至現有執行個體。

  1. 在 EC2 主控台中，移至 [Network Interfaces (網路界面)]。

  1. 按一下 [Create a Network Interface (建立網路界面)]。

  1. 選取您的執行個體所在的相同子網路。

  1. 請務必啟用「彈性布料轉接器」，然後按一下建立。

  1. 返回 [EC2 Instances (EC2 執行個體)] 索引標籤並選取您的執行個體。

  1. 前往動作：執行個體狀態，並在連接 EFA 之前停止執行個體。

  1. 從 [Actions (動作)] 中，選取 [Networking: Attach Network Interface (聯網：連接網路界面)]。

  1. 選擇您剛建立的界面，然後按一下連接。

  1. 重新啟動您的執行個體。

### 從執行個體
<a name="tutorial-efa-verify-attachment-instance"></a>

下列測試指令碼已存在於 DLAMI 上。執行它以確保核心模組已正確載入。

```
$ fi_info -p efa
```

您的輸出應該類似以下內容：

```
provider: efa
    fabric: EFA-fe80::e5:56ff:fe34:56a8
    domain: efa_0-rdm
    version: 2.0
    type: FI_EP_RDM
    protocol: FI_PROTO_EFA
provider: efa
    fabric: EFA-fe80::e5:56ff:fe34:56a8
    domain: efa_0-dgrm
    version: 2.0
    type: FI_EP_DGRAM
    protocol: FI_PROTO_EFA
provider: efa;ofi_rxd
    fabric: EFA-fe80::e5:56ff:fe34:56a8
    domain: efa_0-dgrm
    version: 1.0
    type: FI_EP_RDM
    protocol: FI_PROTO_RXD
```

### 確認安全群組組態
<a name="tutorial-efa-verify-attachment-security"></a>

下列測試指令碼已存在於 DLAMI 上。執行它以確保您建立的安全群組已正確設定。

```
$ cd /opt/amazon/efa/test/ 
$ ./efa_test.sh
```

您的輸出應該類似以下內容：

```
Starting server...
Starting client...
bytes   #sent   #ack     total       time     MB/sec    usec/xfer   Mxfers/sec
64      10      =10      1.2k        0.02s      0.06    1123.55       0.00
256     10      =10      5k          0.00s     17.66      14.50       0.07
1k      10      =10      20k         0.00s     67.81      15.10       0.07
4k      10      =10      80k         0.00s    237.45      17.25       0.06
64k     10      =10      1.2m        0.00s    921.10      71.15       0.01
1m      10      =10      20m         0.01s   2122.41     494.05       0.00
```

如果停止回應或未完成，請確保您的安全群組具有正確的傳入/傳出規則。

# 在 DLAMI 上使用 EFA
<a name="tutorial-efa-using"></a>

下一節說明如何使用 EFA 在 上執行多節點應用程式 AWS 深度學習 AMIs。

## 使用 EFA 執行多節點應用程式
<a name="tutorial-efa-using-multi-node"></a>

若要跨節點叢集執行應用程式，需要下列組態

**Topics**
+ [啟用無密碼 SSH](#tutorial-efa-using-multi-node-ssh)
+ [建立主機檔案](#tutorial-efa-using-multi-node-hosts)
+ [NCCL 測試](#tutorial-efa-using-2node)

### 啟用無密碼 SSH
<a name="tutorial-efa-using-multi-node-ssh"></a>

在叢集中選取一個節點做為領導節點。其餘的節點稱為成員節點。

1. 在領導節點上，產生 RSA 金鑰對。

   ```
   ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
   ```

1. 變更領導節點上私有金鑰的許可。

   ```
   chmod 600 ~/.ssh/id_rsa
   ```

1. 將公有金鑰複製到 ，`~/.ssh/id_rsa.pub`並將其附加到叢集中成員節點`~/.ssh/authorized_keys`的 。

1. 您現在應該可以使用私有 IP 直接從領導節點登入到成員節點。

   ```
   ssh <member private ip>
   ```

1. 在領導節點上的 \$1/.ssh/config 檔案中加入以下內容，以停用 strictHostKeyChecking 並啟用領導節點上的代理程式轉送：

   ```
   Host *
       ForwardAgent yes
   Host *
       StrictHostKeyChecking no
   ```

1. 在 Amazon Linux 2 執行個體上，在領導節點上執行下列命令，以提供組態檔案的正確許可：

   ```
   chmod 600 ~/.ssh/config
   ```

### 建立主機檔案
<a name="tutorial-efa-using-multi-node-hosts"></a>

在領導節點上，建立主機檔案以識別叢集中的節點。主機檔案對於叢集中每個節點都必須有項目。建立一個檔案 \$1/hosts，並使用私有 IP 新增每個節點，如下所示：

```
localhost slots=8
<private ip of node 1> slots=8
<private ip of node 2> slots=8
```

### NCCL 測試
<a name="tutorial-efa-using-2node"></a>

**注意**  
這些測試已使用 EFA 1.38.0 版和 OFI NCCL 外掛程式 1.13.2 執行。

 下列是 Nvidia 提供的 NCCL 測試子集，用於測試多個運算節點的功能和效能 

 **支援的執行個體：P3dn, P4, P5, P5e, P5en** 

#### 效能測試
<a name="tutorial-efa-using-multinode"></a>

##### P4d.24xlarge 上的多節點 NCCL 效能測試
<a name="tutorial-efa-using-multi-node-performance"></a>

若要使用 EFA 檢查 NCCL 效能，請執行官方 NCCL[-Tests 儲存庫上可用的標準 NCCL](https://github.com/NVIDIA/nccl-tests.git) 效能測試。DLAMI 隨附針對 CUDA XX.X 建置的測試。 您可以同樣使用 EFA 執行自己的指令碼。

建構您自己的指令碼時，請參閱下列指引：
+ 使用 EFA 執行 NCCL 應用程式時，請使用 mpirun 的完整路徑，如範例所示。
+ 根據叢集中的執行個體和 GPU 的數目來變更參數 np 和 N。
+ 新增 NCCL\$1DEBUG=INFO 旗標，並確保日誌指出 EFA 用量為 "Selected Provider is EFA"。
+  將訓練日誌位置設定為剖析以進行驗證 

  ```
  TRAINING_LOG="testEFA_$(date +"%N").log"
  ```

在任何成員節點上使用命令 `watch nvidia-smi` 來監視 GPU 使用量。下列`watch nvidia-smi`命令適用於一般 CUDA xx.x 版本，並取決於執行個體的作業系統。您可以取代指令碼中的 CUDA 版本，為 Amazon EC2 執行個體中的任何可用 CUDA 版本執行命令。
+ Amazon Linux 2、Amazon Linux 2023：

  ```
   $ /opt/amazon/openmpi/bin/mpirun -n 16 -N 8 \
  -x NCCL_DEBUG=INFO --mca pml ^cm \
  -x LD_LIBRARY_PATH=/usr/local/cuda-xx.x/efa/lib:/usr/local/cuda-xx.x/lib:/usr/local/cuda-xx.x/lib64:/usr/local/cuda-xx.x:/opt/amazon/efa/lib64:/opt/amazon/openmpi/lib64:$LD_LIBRARY_PATH \
  --hostfile hosts --mca btl tcp,self --mca btl_tcp_if_exclude lo,docker0 --bind-to none \
  /usr/local/cuda-xx.x/efa/test-cuda-xx.x/all_reduce_perf -b 8 -e 1G -f 2 -g 1 -c 1 -n 100 | tee ${TRAINING_LOG}
  ```
+ Ubuntu 20.04、Ubuntu 20.04：

  ```
  $ /opt/amazon/openmpi/bin/mpirun -n 16 -N 8 \
  -x NCCL_DEBUG=INFO --mca pml ^cm \
  -x LD_LIBRARY_PATH=/usr/local/cuda-xx.x/efa/lib:/usr/local/cuda-xx.x/lib:/usr/local/cuda-xx.x/lib64:/usr/local/cuda-xx.x:/opt/amazon/efa/lib:/opt/amazon/openmpi/lib:$LD_LIBRARY_PATH \
  --hostfile hosts --mca btl tcp,self --mca btl_tcp_if_exclude lo,docker0 --bind-to none \
  /usr/local/cuda-xx.x/efa/test-cuda-xx.x/all_reduce_perf -b 8 -e 1G -f 2 -g 1 -c 1 -n 100 | tee ${TRAINING_LOG}
  ```

您的輸出看起來應如以下所示：

```
# nThread 1 nGpus 1 minBytes 8 maxBytes 1073741824 step: 2(factor) warmup iters: 5 iters: 100 agg iters: 1 validation: 1 graph: 0
#
# Using devices
#  Rank  0 Group  0 Pid  33378 on ip-172-31-42-25 device  0 [0x10] NVIDIA A100-SXM4-40GB
#  Rank  1 Group  0 Pid  33379 on ip-172-31-42-25 device  1 [0x10] NVIDIA A100-SXM4-40GB
#  Rank  2 Group  0 Pid  33380 on ip-172-31-42-25 device  2 [0x20] NVIDIA A100-SXM4-40GB
#  Rank  3 Group  0 Pid  33381 on ip-172-31-42-25 device  3 [0x20] NVIDIA A100-SXM4-40GB
#  Rank  4 Group  0 Pid  33382 on ip-172-31-42-25 device  4 [0x90] NVIDIA A100-SXM4-40GB
#  Rank  5 Group  0 Pid  33383 on ip-172-31-42-25 device  5 [0x90] NVIDIA A100-SXM4-40GB
#  Rank  6 Group  0 Pid  33384 on ip-172-31-42-25 device  6 [0xa0] NVIDIA A100-SXM4-40GB
#  Rank  7 Group  0 Pid  33385 on ip-172-31-42-25 device  7 [0xa0] NVIDIA A100-SXM4-40GB
#  Rank  8 Group  0 Pid  30378 on ip-172-31-43-8 device  0 [0x10] NVIDIA A100-SXM4-40GB
#  Rank  9 Group  0 Pid  30379 on ip-172-31-43-8 device  1 [0x10] NVIDIA A100-SXM4-40GB
#  Rank 10 Group  0 Pid  30380 on ip-172-31-43-8 device  2 [0x20] NVIDIA A100-SXM4-40GB
#  Rank 11 Group  0 Pid  30381 on ip-172-31-43-8 device  3 [0x20] NVIDIA A100-SXM4-40GB
#  Rank 12 Group  0 Pid  30382 on ip-172-31-43-8 device  4 [0x90] NVIDIA A100-SXM4-40GB
#  Rank 13 Group  0 Pid  30383 on ip-172-31-43-8 device  5 [0x90] NVIDIA A100-SXM4-40GB
#  Rank 14 Group  0 Pid  30384 on ip-172-31-43-8 device  6 [0xa0] NVIDIA A100-SXM4-40GB
#  Rank 15 Group  0 Pid  30385 on ip-172-31-43-8 device  7 [0xa0] NVIDIA A100-SXM4-40GB
ip-172-31-42-25:33385:33385 [7] NCCL INFO cudaDriverVersion 12060
ip-172-31-43-8:30383:30383 [5] NCCL INFO Bootstrap : Using ens32:172.31.43.8
ip-172-31-43-8:30383:30383 [5] NCCL INFO NCCL version 2.23.4+cuda12.5
...
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Initializing aws-ofi-nccl 1.13.2-aws
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Using Libfabric version 1.22
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Using CUDA driver version 12060 with runtime 12050
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Configuring AWS-specific options
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Setting provider_filter to efa
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Setting FI_EFA_FORK_SAFE environment variable to 1
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Setting NCCL_NVLSTREE_MAX_CHUNKSIZE to 512KiB
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Setting NCCL_NVLS_CHUNKSIZE to 512KiB
ip-172-31-42-25:33384:33451 [6] NCCL INFO NET/OFI Running on p4d.24xlarge platform, Setting NCCL_TOPO_FILE environment variable to /opt/amazon/ofi-nccl/share/aws-ofi-nccl/xml/p4d-24xl-topo.xml
...
-----------------------------some output truncated-----------------------------------
#                                                              out-of-place                       in-place          
#       size         count      type   redop    root     time   algbw   busbw #wrong     time   algbw   busbw #wrong
#        (B)    (elements)                               (us)  (GB/s)  (GB/s)            (us)  (GB/s)  (GB/s)       
           8             2     float     sum      -1    180.3    0.00    0.00      0    179.3    0.00    0.00      0
          16             4     float     sum      -1    178.1    0.00    0.00      0    177.6    0.00    0.00      0
          32             8     float     sum      -1    178.5    0.00    0.00      0    177.9    0.00    0.00      0
          64            16     float     sum      -1    178.8    0.00    0.00      0    178.7    0.00    0.00      0
         128            32     float     sum      -1    178.2    0.00    0.00      0    177.8    0.00    0.00      0
         256            64     float     sum      -1    178.6    0.00    0.00      0    178.8    0.00    0.00      0
         512           128     float     sum      -1    177.2    0.00    0.01      0    177.1    0.00    0.01      0
        1024           256     float     sum      -1    179.2    0.01    0.01      0    179.3    0.01    0.01      0
        2048           512     float     sum      -1    181.3    0.01    0.02      0    181.2    0.01    0.02      0
        4096          1024     float     sum      -1    184.2    0.02    0.04      0    183.9    0.02    0.04      0
        8192          2048     float     sum      -1    191.2    0.04    0.08      0    190.6    0.04    0.08      0
       16384          4096     float     sum      -1    202.5    0.08    0.15      0    202.3    0.08    0.15      0
       32768          8192     float     sum      -1    233.0    0.14    0.26      0    232.1    0.14    0.26      0
       65536         16384     float     sum      -1    238.6    0.27    0.51      0    235.1    0.28    0.52      0
      131072         32768     float     sum      -1    237.2    0.55    1.04      0    236.8    0.55    1.04      0
      262144         65536     float     sum      -1    248.3    1.06    1.98      0    247.0    1.06    1.99      0
      524288        131072     float     sum      -1    309.2    1.70    3.18      0    307.7    1.70    3.20      0
     1048576        262144     float     sum      -1    408.7    2.57    4.81      0    404.3    2.59    4.86      0
     2097152        524288     float     sum      -1    613.5    3.42    6.41      0    607.9    3.45    6.47      0
     4194304       1048576     float     sum      -1    924.5    4.54    8.51      0    914.8    4.58    8.60      0
     8388608       2097152     float     sum      -1   1059.5    7.92   14.85      0   1054.3    7.96   14.92      0
    16777216       4194304     float     sum      -1   1269.9   13.21   24.77      0   1272.0   13.19   24.73      0
    33554432       8388608     float     sum      -1   1642.7   20.43   38.30      0   1636.7   20.50   38.44      0
    67108864      16777216     float     sum      -1   2446.7   27.43   51.43      0   2445.8   27.44   51.45      0
   134217728      33554432     float     sum      -1   4143.6   32.39   60.73      0   4142.4   32.40   60.75      0
   268435456      67108864     float     sum      -1   7351.9   36.51   68.46      0   7346.7   36.54   68.51      0
   536870912     134217728     float     sum      -1    13717   39.14   73.39      0    13703   39.18   73.46      0
  1073741824     268435456     float     sum      -1    26416   40.65   76.21      0    26420   40.64   76.20      0
...
# Out of bounds values : 0 OK
# Avg bus bandwidth    : 15.5514
```

#### 驗證測試
<a name="tutorial-efa-validation"></a>

若要驗證 EFA 測試是否傳回有效的結果，請使用下列測試來確認：
+ 使用 EC2 執行個體中繼資料取得執行個體類型：

  ```
  TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
  INSTANCE_TYPE=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/instance-type)
  ```
+ 執行 [效能測試](#tutorial-efa-using-multinode) 
+  設定下列參數 

  ```
  CUDA_VERSION
  CUDA_RUNTIME_VERSION
  NCCL_VERSION
  ```
+  驗證結果，如下所示：

  ```
  RETURN_VAL=`echo $?`
  if [ ${RETURN_VAL} -eq 0 ]; then
  
      # [0] NCCL INFO NET/OFI Initializing aws-ofi-nccl 1.13.2-aws
      # [0] NCCL INFO NET/OFI Using CUDA driver version 12060 with runtime 12010
  
      # cudaDriverVersion 12060  --> This is max supported cuda version by nvidia driver
      # NCCL version 2.23.4+cuda12.5 --> This is NCCL version compiled with cuda version
  
      # Validation of logs
      grep "NET/OFI Configuring AWS-specific options" ${TRAINING_LOG} || { echo "AWS-specific options text not found"; exit 1; } 
      grep "busbw" ${TRAINING_LOG} || { echo "busbw text not found"; exit 1; } 
      grep "Avg bus bandwidth " ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; } 
      grep "NCCL version $NCCL_VERSION" ${TRAINING_LOG} || { echo "Text not found: NCCL version $NCCL_VERSION"; exit 1; }
      if [[ ${INSTANCE_TYPE} == "p4d.24xlarge" ]]; then
          grep "NET/Libfabric/0/GDRDMA" ${TRAINING_LOG} || { echo "Text not found: NET/Libfabric/0/GDRDMA"; exit 1; }  
          grep "NET/OFI Selected Provider is efa (found 4 nics)" ${TRAINING_LOG} || { echo "Selected Provider is efa text not found"; exit 1; }   
      elif [[ ${INSTANCE_TYPE} == "p4de.24xlarge" ]]; then
          grep "NET/Libfabric/0/GDRDMA" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
          grep "NET/OFI Selected Provider is efa (found 4 nics)" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
      elif [[ ${INSTANCE_TYPE} == "p5.48xlarge" ]]; then
          grep "NET/Libfabric/0/GDRDMA" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
          grep "NET/OFI Selected Provider is efa (found 32 nics)" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; } 
      elif [[ ${INSTANCE_TYPE} == "p5e.48xlarge" ]]; then
          grep "NET/Libfabric/0/GDRDMA" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
          grep "NET/OFI Selected Provider is efa (found 32 nics)" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
      elif [[ ${INSTANCE_TYPE} == "p5en.48xlarge" ]]; then
          grep "NET/Libfabric/0/GDRDMA" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
          grep "NET/OFI Selected Provider is efa (found 16 nics)" ${TRAINING_LOG} || { echo "Avg bus bandwidth text not found"; exit 1; }
      elif [[ ${INSTANCE_TYPE} == "p3dn.24xlarge" ]]; then
          grep "NET/OFI Selected Provider is efa (found 4 nics)" ${TRAINING_LOG} || { echo "Selected Provider is efa text not found"; exit 1; }  
      fi
      echo "***************************** check_efa_nccl_all_reduce passed for cuda version ${CUDA_VERSION} *****************************"
  else
      echo "***************************** check_efa_nccl_all_reduce failed for cuda version ${CUDA_VERSION} *****************************"
  fi
  ```
+ 若要存取基準資料，我們可以剖析多節點 all\$1reduce 測試的資料表輸出最後一列：

  ```
  benchmark=$(sudo cat ${TRAINING_LOG} | grep '1073741824' | tail -n1 | awk -F " " '{{print $12}}' | sed 's/ //' | sed  's/  5e-07//')
  if [[ -z "${benchmark}" ]]; then
    echo "benchmark variable is empty"
    exit 1
  fi
  
  echo "Benchmark throughput: ${benchmark}"
  ```

# GPU 監控和最佳化
<a name="tutorial-gpu"></a>

下一節將引導您完成 GPU 最佳化和監控選項。本節的編排像一般的工作流程，包括監控、監督、預先處理和培訓。
+ [監控](tutorial-gpu-monitoring.md)
  + [使用 CloudWatch 監控 GPU](tutorial-gpu-monitoring-gpumon.md)
+ [最佳化](tutorial-gpu-opt.md)
  + [預處理](tutorial-gpu-opt-preprocessing.md)
  + [培訓](tutorial-gpu-opt-training.md)

# 監控
<a name="tutorial-gpu-monitoring"></a>

您的 DLAMI 預先安裝了數種 GPU 監控工具。本指南還提及可供下載和安裝的工具。
+ [使用 CloudWatch 監控 GPU](tutorial-gpu-monitoring-gpumon.md) - 預先安裝的公用程式，可將 GPU 用量統計資料報告給 Amazon CloudWatch。
+ [nvidia-smi CLI](https://developer.nvidia.com/nvidia-system-management-interface) - 用於監控整體 GPU 運算和記憶體使用率的公用程式。這已預先安裝在您的 AWS 深度學習 AMIs (DLAMI) 上。
+ [NVML C 程式庫](https://developer.nvidia.com/nvidia-management-library-nvml) – 以 C 為基礎的 API，可直接存取 GPU 監控和管理功能。這是由 nvidia-smi CLI 在幕後使用，並預先安裝在 DLAMI 上。它還有 Python 和 Perl 繫結，有助於以這些語言來開發。預先安裝在 DLAMI 的 gpumon.py 公用程式使用 [nvidia-ml-py](https://pypi.org/project/nvidia-ml-py/) 中的 pynvml 套件。
+ [NVIDIA DCGM](https://developer.nvidia.com/data-center-gpu-manager-dcgm) - 叢集管理工具。造訪開發人員頁面，了解如何安裝和設定這個工具。

**提示**  
如需使用已安裝 DLAMI 之 CUDA 工具的最新資訊，請參閱 NVIDIA 的開發人員部落格：  
[使用 Nsight IDE 和 nvprof 監控 TensorCore 使用率](https://devblogs.nvidia.com/using-nsight-compute-nvprof-mixed-precision-deep-learning-models/)。

# 使用 CloudWatch 監控 GPU
<a name="tutorial-gpu-monitoring-gpumon"></a>

當您使用 DLAMI 搭配 GPU 時，您可能會發現您在培訓或推論期間設法追蹤其使用狀況。這在最佳化資料管道和調校深度學習網路時可能有很用。

使用 CloudWatch 設定 GPU 指標的方法有兩種：
+ [使用 AWS CloudWatch 代理程式設定指標 （建議）](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-guide)
+ [使用預先安裝的`gpumon.py`指令碼設定指標](#tutorial-gpu-monitoring-gpumon-script)

## 使用 AWS CloudWatch 代理程式設定指標 （建議）
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-guide"></a>

將您的 DLAMI 與[統一的 CloudWatch 代理程式](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html)整合，以設定 GPU 指標並監控 Amazon EC2 加速執行個體中 GPU 協同程序的使用率。

使用 DLAMI 設定 [GPU 指標](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-NVIDIA-GPU.html)有四種方式：
+ [設定最小 GPU 指標](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-minimal)
+ [設定部分 GPU 指標](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-partial)
+ [設定所有可用的 GPU 指標](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-all)
+ [設定自訂 GPU 指標](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-custom)

如需更新和安全性修補程式的相關資訊，請參閱 [AWS CloudWatch 代理程式的安全修補](#tutorial-gpu-monitoring-gpumon-cloudwatch-agent-security)

### 先決條件
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-prerequisites"></a>

若要開始使用，您必須設定允許執行個體將指標推送至 CloudWatch 的 Amazon EC2 執行個體 IAM 許可。如需詳細步驟，請參閱[建立 IAM 角色和使用者以搭配 CloudWatch 代理程式使用](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html)。

### 設定最小 GPU 指標
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-minimal"></a>

使用 `dlami-cloudwatch-agent@minimal``systemd`服務設定最少的 GPU 指標。此服務會設定下列指標：
+ `utilization_gpu`
+ `utilization_memory`

您可以在下列位置找到最低預先設定 GPU 指標`systemd`的服務：

```
/opt/aws/amazon-cloudwatch-agent/etc/dlami-amazon-cloudwatch-agent-minimal.json
```

使用下列命令啟用和啟動`systemd`服務：

```
sudo systemctl enable dlami-cloudwatch-agent@minimal
sudo systemctl start dlami-cloudwatch-agent@minimal
```

### 設定部分 GPU 指標
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-partial"></a>

使用 `dlami-cloudwatch-agent@partial``systemd`服務設定部分 GPU 指標。此服務會設定下列指標：
+ `utilization_gpu`
+ `utilization_memory`
+ `memory_total`
+ `memory_used`
+ `memory_free`

您可以在下列位置找到部分預先設定 GPU 指標`systemd`的服務：

```
/opt/aws/amazon-cloudwatch-agent/etc/dlami-amazon-cloudwatch-agent-partial.json
```

使用下列命令啟用和啟動`systemd`服務：

```
sudo systemctl enable dlami-cloudwatch-agent@partial
sudo systemctl start dlami-cloudwatch-agent@partial
```

### 設定所有可用的 GPU 指標
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-all"></a>

使用 `dlami-cloudwatch-agent@all``systemd`服務設定所有可用的 GPU 指標。此服務會設定下列指標：
+ `utilization_gpu`
+ `utilization_memory`
+ `memory_total`
+ `memory_used`
+ `memory_free`
+ `temperature_gpu`
+ `power_draw`
+ `fan_speed`
+ `pcie_link_gen_current`
+ `pcie_link_width_current`
+ `encoder_stats_session_count`
+ `encoder_stats_average_fps`
+ `encoder_stats_average_latency`
+ `clocks_current_graphics`
+ `clocks_current_sm`
+ `clocks_current_memory`
+ `clocks_current_video`

您可以在下列位置找到所有可用預先設定 GPU 指標的 `systemd`服務：

```
/opt/aws/amazon-cloudwatch-agent/etc/dlami-amazon-cloudwatch-agent-all.json
```

使用下列命令啟用和啟動`systemd`服務：

```
sudo systemctl enable dlami-cloudwatch-agent@all
sudo systemctl start dlami-cloudwatch-agent@all
```

### 設定自訂 GPU 指標
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-custom"></a>

如果預先設定的指標不符合您的需求，您可以建立自訂 CloudWatch 代理程式組態檔案。

#### 建立自訂組態檔案
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-custom-create"></a>

若要建立自訂組態檔案，請參閱[手動建立或編輯 CloudWatch 代理程式組態檔案中](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)的詳細步驟。

在此範例中，假設結構描述定義位於 `/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json`。

#### 使用自訂檔案設定指標
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-custom-configure"></a>

執行下列命令，根據您的自訂檔案設定 CloudWatch 代理程式：

```
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config -m ec2 -s -c \
file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
```

### AWS CloudWatch 代理程式的安全修補
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-security"></a>

新發行DLAMIs 會使用最新的可用 AWS CloudWatch 代理程式安全修補程式進行設定。請參閱下列各節，根據您選擇的作業系統，使用最新的安全修補程式更新您目前的 DLAMI。

#### Amazon Linux 2
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-security-al2"></a>

使用 `yum` 取得 Amazon Linux 2 DLAMI 的最新 AWS CloudWatch 代理程式安全修補程式。

```
 sudo yum update
```

#### Ubuntu
<a name="tutorial-gpu-monitoring-gpumon-cloudwatch-agent-security-ubuntu"></a>

若要使用 Ubuntu 取得 DLAMI 的最新 AWS CloudWatch 安全修補程式，必須使用 Amazon S3 下載連結重新安裝 AWS CloudWatch 代理程式。

```
wget https://s3.region.amazonaws.com/amazoncloudwatch-agent-region/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb
```

如需使用 Amazon S3 下載連結安裝 AWS CloudWatch 代理程式的詳細資訊，請參閱[在您的伺服器上安裝和執行 CloudWatch 代理程式](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html)。

## 使用預先安裝的`gpumon.py`指令碼設定指標
<a name="tutorial-gpu-monitoring-gpumon-script"></a>

稱為 gpumon.py 的公用程式已預先安裝在 DLAMI 上。它與 CloudWatch 整合，且支援監控每個 GPU 用量：GPU 記憶體、GPU 溫度和 GPU 電源。此指令碼定期將監控的資料傳送到 CloudWatch。您可以在指令碼中變更幾項設定，以設定要傳送至 CloudWatch 的資料的精細程度。不過，在啟動指令碼之前，您需要設定 CloudWatch 來接收指標。

**如何使用 CloudWatch 來設定和執行 GPU 監控**

1. 建立 IAM 使用者，或修改現有的 IAM 使用者，以利用政策將指標發佈到 CloudWatch。如果您建立新的使用者，請記下登入資料，因為您在下一步驟中需要用到。

   要搜尋的 IAM 政策是 “cloudwatch:PutMetricData”。新增的政策如下所示：

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
           {
               "Action": [
                   "cloudwatch:PutMetricData"
                ],
                "Effect": "Allow",
                "Resource": "*"
           }
      ]
   }
   ```

------
**提示**  
如需有關建立 IAM 使用者和為 CloudWatch 新增政策的詳細資訊，請參閱 [ CloudWatch 文件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html)。

1. 在您的 DLAMI 上，執行[AWS 設定](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html#cli-quick-configuration)並指定 IAM 使用者登入資料。

   ```
   $ aws configure
   ```

1. 執行 gpumon 公用程式之前，您可能需要對它進行一些修改。您可以在下列程式碼區塊中定義的位置中找到 gpumon 公用程式和 README。如需`gpumon.py`指令碼的詳細資訊，請參閱[指令碼的 Amazon S3 位置。](https://s3.amazonaws.com/aws-bigdata-blog/artifacts/GPUMonitoring/gpumon.py)

   ```
   Folder: ~/tools/GPUCloudWatchMonitor
   Files: 	~/tools/GPUCloudWatchMonitor/gpumon.py
         	~/tools/GPUCloudWatchMonitor/README
   ```

   選項：
   + 如果您的執行個體「不在」us-east-1 中，請在 gpumon.py 中變更區域。
   + 變更其他參數 (例如 CloudWatch `namespace`) 或報告期間 (使用 `store_reso`)。

1. 此指令碼目前僅支援 Python 3。啟用您偏好的架構的 Python 3 環境，或啟用 DLAMI 一般 Python 3 環境。

   ```
   $ source activate python3
   ```

1. 在背景執行 gpumon 公用程式。

   ```
   (python3)$ python gpumon.py &
   ```

1. 開啟您的瀏覽器至 [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)，然後選取指標。它會有命名空間 'DeepLearningTrain'。
**提示**  
您可以修改 gpumon.py 來變更命名空間。您也可以調整 `store_reso` 來修改報告間隔。

以下是範例 CloudWatch 圖表報告，顯示執行 gpumon.py 來監控 p2.8xlarge 執行個體上的培訓任務。

![\[CloudWatch 上的 GPU 監控\]](http://docs.aws.amazon.com/zh_tw/dlami/latest/devguide/images/gpumon.png)


對於 GPU 監控和最佳化，您可能有興趣看其他這些主題：
+ [監控](tutorial-gpu-monitoring.md)
  + [使用 CloudWatch 監控 GPU](#tutorial-gpu-monitoring-gpumon)
+ [最佳化](tutorial-gpu-opt.md)
  + [預處理](tutorial-gpu-opt-preprocessing.md)
  + [培訓](tutorial-gpu-opt-training.md)

# 最佳化
<a name="tutorial-gpu-opt"></a>

為了充分利用您的 GPU，您可以最佳化資料管道及調整深度學習網路。如下圖所述，神經網路的單純或基本實作使用 GPU 的方式可能不一致，而未完全發揮其潛能。當您最佳化您的前處理和資料載入時，您可以降低從 CPU 到 GPU 的瓶頸。您可以使用雜合 (當架構支援時)、調整批次大小和同步化呼叫，以調整神經網路本身。您在大多數架構中也可以使用多精確度 (float16 或 int8) 培訓，這可以大幅影響提高輸送量。

下列圖表顯示套用不同的最佳化時累積的效能提升。您的結果將取決於您處理的資料和您最佳化的網路。

![\[GPU 的效能增強\]](http://docs.aws.amazon.com/zh_tw/dlami/latest/devguide/images/performance-enhancements.png)


下列指南介紹可搭配 DLAMI 使用的選項，並協助您提升 GPU 效能。

**Topics**
+ [預處理](tutorial-gpu-opt-preprocessing.md)
+ [培訓](tutorial-gpu-opt-training.md)

# 預處理
<a name="tutorial-gpu-opt-preprocessing"></a>

透過轉換或擴增的資料預先處理通常是 CPU 密集型程序，這可能成為整個管道中的瓶頸。架構有用於影像處理的內建運算子，但 DALI (Data Augmentation Library) 展現比架構的內建選項更好的效能。
+ NVIDIA Data Augmentation Library (DALI)：DALI 將資料擴增卸載到 GPU。它不會預先安裝在 DLAMI 上，但您可以透過在 DLAMI 或其他 Amazon Elastic Compute Cloud 執行個體上安裝或載入支援的架構容器來存取它。如需詳細資訊，請參閱 NVIDIA 網站上的 [DALI 專案頁面](https://docs.nvidia.com/deeplearning/sdk/dali-install-guide/index.html)。如需範例使用案例和下載程式碼範例，請參閱 [ SageMaker 預先處理訓練效能](https://github.com/aws-samples/sagemaker-cv-preprocessing-training-performance)範例。
+ nvJPEG：適用於 C 程式設計人員的 GPU 加速 JPEG 解碼器程式庫。它支援解碼單一映像或批次，以及深度學習中常見的後續轉換操作。nvJPEG 內建於 DALI，或者，您可以另外從 [NVIDIA 網站的 nvjpeg 頁面](https://developer.nvidia.com/nvjpeg)下載來使用。

對於 GPU 監控和最佳化，您可能有興趣看其他這些主題：
+ [監控](tutorial-gpu-monitoring.md)
  + [使用 CloudWatch 監控 GPU](tutorial-gpu-monitoring-gpumon.md)
+ [最佳化](tutorial-gpu-opt.md)
  + [預處理](#tutorial-gpu-opt-preprocessing)
  + [培訓](tutorial-gpu-opt-training.md)

# 培訓
<a name="tutorial-gpu-opt-training"></a>

透過混合精度培訓，您可以使用相同的記憶體數量來部署更大的網路，或相較於單一或雙精度網路而言，降低記憶體使用量，您將會看到運算效能提高。您也可享有較小和更快資料傳輸的好處，這是多節點分散式培訓的重要因素。若要利用混合精度培訓，您需要調整資料轉換和損耗縮放。以下指南說明如何對支援混合精度的架構這樣做。
+ [NVIDIA 深度學習軟體開發套件](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/) - NVIDIA 網站上的文件，描述適用於 MXNet、PyTorch 和 TensorFlow 的混合精度實作。

**提示**  
請務必到網站上查看您選擇的架構，並搜尋「混合精度」或 "fp16" 以取得最新的最佳化技術。以下是您可能覺得很有用的一些混合精度指南：  
[以 TensorFlow 進行混合精度培訓 (影片)](https://devblogs.nvidia.com/mixed-precision-resnet-50-tensor-cores/) - 在 NVIDIA 部落格網站。
[使用 float16 搭配 MXNet 進行混合精度培訓](https://mxnet.apache.org/api/faq/float16) - MXNet 網站上的常見問答集文章。
[NVIDIA Apex：以 PyTorch 輕鬆進行混合精度培訓的工具](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/) - NVIDIA 網站上的部落格文章。

對於 GPU 監控和最佳化，您可能有興趣看其他這些主題：
+ [監控](tutorial-gpu-monitoring.md)
  + [使用 CloudWatch 監控 GPU](tutorial-gpu-monitoring-gpumon.md)
+ [最佳化](tutorial-gpu-opt.md)
  + [預處理](tutorial-gpu-opt-preprocessing.md)
  + [培訓](#tutorial-gpu-opt-training)

# 具有 DLAMI AWS 的 Inferentia Chip
<a name="tutorial-inferentia"></a>

AWS Inferentia 是由 設計的自訂機器學習晶片 AWS ，可用於高效能推論預測。 若要使用晶片，請設定 Amazon Elastic Compute Cloud 執行個體，並使用 AWS Neuron 軟體開發套件 (SDK) 來叫用 Inferentia 晶片。為了為客戶提供最佳的 Inferentia 體驗，Neuron 已內建在 AWS 深度學習 AMIs (DLAMI) 中。

下列主題說明如何開始使用 Inferentia 搭配 DLAMI。

**Topics**
+ [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md)
+ [搭配 AWS Neuron 使用 DLAMI](tutorial-inferentia-using.md)

# 使用 AWS Neuron 啟動 DLAMI 執行個體
<a name="tutorial-inferentia-launching"></a>

 最新的 DLAMI 已準備好與 AWS Inferentia 搭配使用，並隨附 AWS Neuron API 套件。若要啟動 DLAMI 執行個體，請參閱 [啟動和設定 DLAMI。](https://docs.aws.amazon.com/dlami/latest/devguide/launch-config.html)在您擁有 DLAMI 之後，請使用此處的步驟，以確保您的 AWS Inferentia 晶片和 AWS Neuron 資源處於作用中狀態。

**Topics**
+ [驗證您的執行個體](#tutorial-inferentia-launching-verify)
+ [識別 AWS Inferentia 裝置](#tutorial-inferentia-launching-identify)
+ [檢視資源使用量](#tutorial-inferentia-launching-resource-usage)
+ [使用 Neuron Monitor （神經監視器）](#tutorial-inferentia-launching-neuron-monitor)
+ [升級 Neuron 軟體](#tutorial-inferentia-launching-upgrade)

## 驗證您的執行個體
<a name="tutorial-inferentia-launching-verify"></a>

 使用執行個體之前，請確認已正確設定並設定 Neuron。

## 識別 AWS Inferentia 裝置
<a name="tutorial-inferentia-launching-identify"></a>

 若要識別執行個體上的 Inferentia 裝置數量，請使用下列命令：

```
neuron-ls
```

 如果您的執行個體已連接 Inferentia 裝置，您的輸出將如下所示：

```
+--------+--------+--------+-----------+--------------+
| NEURON | NEURON | NEURON | CONNECTED |     PCI      |
| DEVICE | CORES  | MEMORY |  DEVICES  |     BDF      |
+--------+--------+--------+-----------+--------------+
| 0      | 4      | 8 GB   | 1         | 0000:00:1c.0 |
| 1      | 4      | 8 GB   | 2, 0      | 0000:00:1d.0 |
| 2      | 4      | 8 GB   | 3, 1      | 0000:00:1e.0 |
| 3      | 4      | 8 GB   | 2         | 0000:00:1f.0 |
+--------+--------+--------+-----------+--------------+
```

 提供的輸出是從 Inf1.6xlarge 執行個體取得，並包含下列資料欄：
+ NEURON 裝置：指派給 NeuronDevice 的邏輯 ID。設定多個執行時間以使用不同的 NeuronDevices 時，會使用此 ID。
+ NEURON CORES：NeuronDevice 中存在的 NeuronCores 數量。 NeuronDevice 
+ NEURON MEMORY：NeuronDevice 中的 DRAM 記憶體數量。
+ CONNECTED DEVICES：連接至 NeuronDevices 的其他 NeuronDevices。
+ PCI BDF：NeuronDevice 的 PCI 匯流排裝置函數 (BDF) ID。

## 檢視資源使用量
<a name="tutorial-inferentia-launching-resource-usage"></a>

 使用 `neuron-top`命令檢視有關 NeuronCore 和 vCPU 使用率、記憶體用量、載入的模型和 Neuron 應用程式的實用資訊。在沒有引數`neuron-top`的情況下啟動 將會顯示使用 NeuronCores 的所有機器學習應用程式的資料。

```
neuron-top
```

 當應用程式使用四個 NeuronCores 時，輸出看起來應該類似下圖：

![\[neuron-top 命令的輸出，並反白顯示四個 NeuronCores 之一的資訊。\]](http://docs.aws.amazon.com/zh_tw/dlami/latest/devguide/images/neuron-top-output.png)


如需監控和最佳化 Neuron 型推論應用程式之資源的詳細資訊，請參閱 [Neuron 工具](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-tools/index.html)。

## 使用 Neuron Monitor （神經監視器）
<a name="tutorial-inferentia-launching-neuron-monitor"></a>

Neuron Monitor 會從系統上執行的 Neuron 執行時間收集指標，並以 JSON 格式將收集的資料串流至 stdout。這些指標會組織成您透過提供組態檔案所設定的指標群組。如需 Neuron Monitor 的詳細資訊，請參閱 [Neuron Monitor 使用者指南](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-tools/neuron-monitor-user-guide.html)。

## 升級 Neuron 軟體
<a name="tutorial-inferentia-launching-upgrade"></a>

如需有關如何在 DLAMI 中更新 Neuron SDK 軟體的資訊，請參閱 AWS Neuron [設定指南](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-intro/neuron-install-guide.html)。

**後續步驟**  
[搭配 AWS Neuron 使用 DLAMI](tutorial-inferentia-using.md)

# 搭配 AWS Neuron 使用 DLAMI
<a name="tutorial-inferentia-using"></a>

 使用 AWS Neuron SDK 的典型工作流程是在編譯伺服器上編譯先前訓練的機器學習模型。之後，將成品分發至 Inf1 執行個體以執行。 AWS 深度學習 AMIs (DLAMI) 預先安裝了您在使用 Inferentia 的 Inf1 執行個體中編譯和執行推論所需的一切。

 下列各節說明如何搭配 Inferentia 使用 DLAMI。

**Topics**
+ [使用 TensorFlow-Neuron 和 AWS Neuron 編譯器](tutorial-inferentia-tf-neuron.md)
+ [使用 AWS Neuron TensorFlow 服務](tutorial-inferentia-tf-neuron-serving.md)
+ [使用 MXNet-Neuron 和 AWS Neuron 編譯器](tutorial-inferentia-mxnet-neuron.md)
+ [使用 MXNet-Neuron 模型服務](tutorial-inferentia-mxnet-neuron-serving.md)
+ [使用 PyTorch-Neuron 和 AWS Neuron 編譯器](tutorial-inferentia-pytorch-neuron.md)

# 使用 TensorFlow-Neuron 和 AWS Neuron 編譯器
<a name="tutorial-inferentia-tf-neuron"></a>

 本教學課程說明如何使用 AWS Neuron 編譯器編譯 Keras ResNet-50 模型，並以 SavedModel 格式將其匯出為儲存的模型。此格式是典型的 TensorFlow 模型可互換格式。您也會學習如何使用範例輸入在 Inf1 執行個體上執行推論。  

 如需 Neuron SDK 的詳細資訊，請參閱 [AWS Neuron SDK 文件](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/tensorflow-neuron/index.html)。

**Topics**
+ [先決條件](#tutorial-inferentia-tf-neuron-prerequisites)
+ [啟動 Conda 環境](#tutorial-inferentia-tf-neuron-activate)
+ [Resnet50 編譯](#tutorial-inferentia-tf-neuron-compilation)
+ [ResNet50 推論](#tutorial-inferentia-tf-neuron-inference)

## 先決條件
<a name="tutorial-inferentia-tf-neuron-prerequisites"></a>

 在使用本教學課程之前，您應該已完成 [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md) 中的設置步驟。您也應該熟悉深度學習和使用 DLAMI。

## 啟動 Conda 環境
<a name="tutorial-inferentia-tf-neuron-activate"></a>

 使用以下命令啟用 TensorFlow-Neuron conda 環境：

```
source activate aws_neuron_tensorflow_p36
```

 若要結束目前的 conda 環境，請執行下列命令：

```
source deactivate
```

## Resnet50 編譯
<a name="tutorial-inferentia-tf-neuron-compilation"></a>

建立一個叫做 **tensorflow\$1compile\$1resnet50.py** 的 Python 指令碼，具有以下內容。這個 Python 指令碼會編譯 Keras ResNet50 模型，並將其匯出為儲存的模型。

```
import os
import time
import shutil
import tensorflow as tf
import tensorflow.neuron as tfn
import tensorflow.compat.v1.keras as keras
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input

# Create a workspace
WORKSPACE = './ws_resnet50'
os.makedirs(WORKSPACE, exist_ok=True)

# Prepare export directory (old one removed)
model_dir = os.path.join(WORKSPACE, 'resnet50')
compiled_model_dir = os.path.join(WORKSPACE, 'resnet50_neuron')
shutil.rmtree(model_dir, ignore_errors=True)
shutil.rmtree(compiled_model_dir, ignore_errors=True)

# Instantiate Keras ResNet50 model
keras.backend.set_learning_phase(0)
model = ResNet50(weights='imagenet')

# Export SavedModel
tf.saved_model.simple_save(
 session            = keras.backend.get_session(),
 export_dir         = model_dir,
 inputs             = {'input': model.inputs[0]},
 outputs            = {'output': model.outputs[0]})

# Compile using Neuron
tfn.saved_model.compile(model_dir, compiled_model_dir)

# Prepare SavedModel for uploading to Inf1 instance
shutil.make_archive(compiled_model_dir, 'zip', WORKSPACE, 'resnet50_neuron')
```

 使用下列命令編譯模型：

```
python tensorflow_compile_resnet50.py
```

編譯程序需要幾分鐘的時間。完成時，您的輸出應如以下所示：

```
...
INFO:tensorflow:fusing subgraph neuron_op_d6f098c01c780733 with neuron-cc
INFO:tensorflow:Number of operations in TensorFlow session: 4638
INFO:tensorflow:Number of operations after tf.neuron optimizations: 556
INFO:tensorflow:Number of operations placed on Neuron runtime: 554
INFO:tensorflow:Successfully converted ./ws_resnet50/resnet50 to ./ws_resnet50/resnet50_neuron
...
```

 ​ 

 編譯之後，儲存的模型會在 **ws\$1resnet50/resnet50\$1neuron.zip** 被壓縮。使用下列命令將模型解壓縮，並下載推論範例影像：

```
unzip ws_resnet50/resnet50_neuron.zip -d .
curl -O https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg
```

## ResNet50 推論
<a name="tutorial-inferentia-tf-neuron-inference"></a>

建立一個叫做 **tensorflow\$1infer\$1resnet50.py** 的 Python 指令碼，具有以下內容。此指令碼使用先前編譯的推論模型，針對下載的模型執行推論。

```
import os
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications import resnet50

# Create input from image
img_sgl = image.load_img('kitten_small.jpg', target_size=(224, 224))
img_arr = image.img_to_array(img_sgl)
img_arr2 = np.expand_dims(img_arr, axis=0)
img_arr3 = resnet50.preprocess_input(img_arr2)
# Load model
COMPILED_MODEL_DIR = './ws_resnet50/resnet50_neuron/'
predictor_inferentia = tf.contrib.predictor.from_saved_model(COMPILED_MODEL_DIR)
# Run inference
model_feed_dict={'input': img_arr3}
infa_rslts = predictor_inferentia(model_feed_dict);
# Display results
print(resnet50.decode_predictions(infa_rslts["output"], top=5)[0])
```

 使用下列命令在模型上執行推論：

```
python tensorflow_infer_resnet50.py
```

 您的輸出看起來應如以下所示：

```
...
[('n02123045', 'tabby', 0.6918919), ('n02127052', 'lynx', 0.12770271), ('n02123159', 'tiger_cat', 0.08277027), ('n02124075', 'Egyptian_cat', 0.06418919), ('n02128757', 'snow_leopard', 0.009290541)]
```

**後續步驟**  
[使用 AWS Neuron TensorFlow 服務](tutorial-inferentia-tf-neuron-serving.md)

# 使用 AWS Neuron TensorFlow 服務
<a name="tutorial-inferentia-tf-neuron-serving"></a>

本教學課程示範如何在匯出儲存的模型以搭配 TensorFlow Serving 使用之前，建構圖形並新增 AWS Neuron 編譯步驟。TensorFlow 服務是一個服務系統，允許您跨網路擴展推斷。Neuron TensorFlow Serving 使用相同的 API 做為一般 TensorFlow Serving。唯一的差別是，必須為 AWS Inferentia 編譯儲存的模型，且進入點是名為 的不同二進位 `tensorflow_model_server_neuron`。二進位檔位於 `/usr/local/bin/tensorflow_model_server_neuron` ，並預先安裝在 DLAMI 中。

 如需 Neuron SDK 的詳細資訊，請參閱 [AWS Neuron SDK 文件](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/tensorflow-neuron/index.html)。

**Topics**
+ [先決條件](#tutorial-inferentia-tf-neuron--serving-prerequisites)
+ [啟動 Conda 環境](#tutorial-inferentia-tf-neuron-serving-activate)
+ [編譯和匯出儲存的模型](#tutorial-inferentia-tf-neuron-serving-compile)
+ [為儲存的模型提供服務](#tutorial-inferentia-tf-neuron-serving-serving)
+ [向模型伺服器產生推論請求](#tutorial-inferentia-tf-neuron-serving-inference)

## 先決條件
<a name="tutorial-inferentia-tf-neuron--serving-prerequisites"></a>

在使用本教學課程之前，您應該已完成 [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md) 中的設置步驟。您也應該熟悉深度學習和使用 DLAMI。

## 啟動 Conda 環境
<a name="tutorial-inferentia-tf-neuron-serving-activate"></a>

 使用以下命令啟用 TensorFlow-Neuron conda 環境：

```
source activate aws_neuron_tensorflow_p36
```

 如果您需要退出目前的 conda 環境，請執行：

```
source deactivate
```

## 編譯和匯出儲存的模型
<a name="tutorial-inferentia-tf-neuron-serving-compile"></a>

使用下列內容建立名為 `tensorflow-model-server-compile.py` 的 Python 指令碼。 此指令碼建構圖形並使用 Neuron 編譯圖形。然後將編譯後的圖形匯出為儲存的模型。  

```
import tensorflow as tf
import tensorflow.neuron
import os

tf.keras.backend.set_learning_phase(0)
model = tf.keras.applications.ResNet50(weights='imagenet')
sess = tf.keras.backend.get_session()
inputs = {'input': model.inputs[0]}
outputs = {'output': model.outputs[0]}

# save the model using tf.saved_model.simple_save
modeldir = "./resnet50/1"
tf.saved_model.simple_save(sess, modeldir, inputs, outputs)

# compile the model for Inferentia
neuron_modeldir = os.path.join(os.path.expanduser('~'), 'resnet50_inf1', '1')
tf.neuron.saved_model.compile(modeldir, neuron_modeldir, batch_size=1)
```

 使用下列命令編譯模型：

```
python tensorflow-model-server-compile.py
```

 您的輸出看起來應如以下所示：

```
...
INFO:tensorflow:fusing subgraph neuron_op_d6f098c01c780733 with neuron-cc
INFO:tensorflow:Number of operations in TensorFlow session: 4638
INFO:tensorflow:Number of operations after tf.neuron optimizations: 556
INFO:tensorflow:Number of operations placed on Neuron runtime: 554
INFO:tensorflow:Successfully converted ./resnet50/1 to /home/ubuntu/resnet50_inf1/1
```

## 為儲存的模型提供服務
<a name="tutorial-inferentia-tf-neuron-serving-serving"></a>

一旦模型已編譯過，您可以使用以下命令，以 tensorflow\$1model\$1server\$1neuron 二進位檔案為儲存的模型提供服務：

```
tensorflow_model_server_neuron --model_name=resnet50_inf1 \
    --model_base_path=$HOME/resnet50_inf1/ --port=8500 &
```

 您的輸出看起來應該如下所示。編譯的模型 由伺服器在 Inferentia 裝置的 DRAM 中暫存，以準備推論。

```
...
2019-11-22 01:20:32.075856: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:311] SavedModel load for tags { serve }; Status: success. Took 40764 microseconds.
2019-11-22 01:20:32.075888: I tensorflow_serving/servables/tensorflow/saved_model_warmup.cc:105] No warmup data file found at /home/ubuntu/resnet50_inf1/1/assets.extra/tf_serving_warmup_requests
2019-11-22 01:20:32.075950: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: resnet50_inf1 version: 1}
2019-11-22 01:20:32.077859: I tensorflow_serving/model_servers/server.cc:353] Running gRPC ModelServer at 0.0.0.0:8500 ...
```

## 向模型伺服器產生推論請求
<a name="tutorial-inferentia-tf-neuron-serving-inference"></a>

建立一個叫做 `tensorflow-model-server-infer.py` 的 Python 指令碼，具有以下內容。此指令碼透過 gRPC (為一服務框架) 執行推斷。

```
import numpy as np
import grpc
import tensorflow as tf
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
from tensorflow.keras.applications.resnet50 import decode_predictions

if __name__ == '__main__':
    channel = grpc.insecure_channel('localhost:8500')
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    img_file = tf.keras.utils.get_file(
        "./kitten_small.jpg",
        "https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg")
    img = image.load_img(img_file, target_size=(224, 224))
    img_array = preprocess_input(image.img_to_array(img)[None, ...])
    request = predict_pb2.PredictRequest()
    request.model_spec.name = 'resnet50_inf1'
    request.inputs['input'].CopyFrom(
        tf.contrib.util.make_tensor_proto(img_array, shape=img_array.shape))
    result = stub.Predict(request)
    prediction = tf.make_ndarray(result.outputs['output'])
    print(decode_predictions(prediction))
```

 使用 gRPC，以下列命令在模型上執行推論：

```
python tensorflow-model-server-infer.py
```

 您的輸出看起來應如以下所示：

```
[[('n02123045', 'tabby', 0.6918919), ('n02127052', 'lynx', 0.12770271), ('n02123159', 'tiger_cat', 0.08277027), ('n02124075', 'Egyptian_cat', 0.06418919), ('n02128757', 'snow_leopard', 0.009290541)]]
```

# 使用 MXNet-Neuron 和 AWS Neuron 編譯器
<a name="tutorial-inferentia-mxnet-neuron"></a>

MXNet-Neuron 編譯 API 提供一種方法來編譯模型圖表，您可以在 AWS Inferentia 裝置上執行。

 在此範例中，您可以使用 API 來編譯 ResNet-50 模型，並使用它來執行推論。

 如需 Neuron SDK 的詳細資訊，請參閱 [AWS Neuron SDK 文件](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/mxnet-neuron/index.html)。

**Topics**
+ [先決條件](#tutorial-inferentia-mxnet-neuron-prerequisites)
+ [啟動 Conda 環境](#tutorial-inferentia-mxnet-neuron-activate)
+ [Resnet50 編譯](#tutorial-inferentia-mxnet-neuron-compilation)
+ [ResNet50 推論](#tutorial-inferentia-mxnet-neuron-inference)

## 先決條件
<a name="tutorial-inferentia-mxnet-neuron-prerequisites"></a>

 在使用本教學課程之前，您應該已完成 [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md) 中的設置步驟。您也應該熟悉深度學習和使用 DLAMI。

## 啟動 Conda 環境
<a name="tutorial-inferentia-mxnet-neuron-activate"></a>

 使用以下命令啟動 MXNet-Neuron conda 環境：

```
source activate aws_neuron_mxnet_p36
```

若要退出目前的 conda 環境，請執行：

```
source deactivate
```

## Resnet50 編譯
<a name="tutorial-inferentia-mxnet-neuron-compilation"></a>

建立一個叫做 **mxnet\$1compile\$1resnet50.py** 的 Python 指令碼，具有以下內容。此指令碼使用 MXNet-Neuron 編譯 Python API 來編譯一個 ResNet-50 模型。

```
import mxnet as mx
import numpy as np

print("downloading...")
path='http://data.mxnet.io/models/imagenet/'
mx.test_utils.download(path+'resnet/50-layers/resnet-50-0000.params')
mx.test_utils.download(path+'resnet/50-layers/resnet-50-symbol.json')
print("download finished.")

sym, args, aux = mx.model.load_checkpoint('resnet-50', 0)

print("compile for inferentia using neuron... this will take a few minutes...")
inputs = { "data" : mx.nd.ones([1,3,224,224], name='data', dtype='float32') }

sym, args, aux = mx.contrib.neuron.compile(sym, args, aux, inputs)

print("save compiled model...")
mx.model.save_checkpoint("compiled_resnet50", 0, sym, args, aux)
```

 使用下列命令編譯模型：

```
python mxnet_compile_resnet50.py
```

 編譯需要幾分鐘的時間。編譯完成 時，下列檔案將位於您目前的目錄中：

```
resnet-50-0000.params
resnet-50-symbol.json
compiled_resnet50-0000.params
compiled_resnet50-symbol.json
```

## ResNet50 推論
<a name="tutorial-inferentia-mxnet-neuron-inference"></a>

建立一個叫做 **mxnet\$1infer\$1resnet50.py** 的 Python 指令碼，具有以下內容。此指令碼會下載範例影像，並使用它來執行具有已編譯模型的推論。

```
import mxnet as mx
import numpy as np

path='http://data.mxnet.io/models/imagenet/'
mx.test_utils.download(path+'synset.txt')

fname = mx.test_utils.download('https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg')
img = mx.image.imread(fname)

# convert into format (batch, RGB, width, height)
img = mx.image.imresize(img, 224, 224) 
# resize
img = img.transpose((2, 0, 1)) 
# Channel first
img = img.expand_dims(axis=0) 
# batchify
img = img.astype(dtype='float32')

sym, args, aux = mx.model.load_checkpoint('compiled_resnet50', 0)
softmax = mx.nd.random_normal(shape=(1,))
args['softmax_label'] = softmax
args['data'] = img
# Inferentia context
ctx = mx.neuron()

exe = sym.bind(ctx=ctx, args=args, aux_states=aux, grad_req='null')
with open('synset.txt', 'r') as f:
    labels = [l.rstrip() for l in f]

exe.forward(data=img)
prob = exe.outputs[0].asnumpy()
# print the top-5
prob = np.squeeze(prob)
a = np.argsort(prob)[::-1] 
for i in a[0:5]:
    print('probability=%f, class=%s' %(prob[i], labels[i]))
```

 使用以下命令，以編譯模型執行推斷：

```
python mxnet_infer_resnet50.py
```

 您的輸出看起來應如以下所示：

```
probability=0.642454, class=n02123045 tabby, tabby cat
probability=0.189407, class=n02123159 tiger cat
probability=0.100798, class=n02124075 Egyptian cat
probability=0.030649, class=n02127052 lynx, catamount
probability=0.016278, class=n02129604 tiger, Panthera tigris
```

**後續步驟**  
[使用 MXNet-Neuron 模型服務](tutorial-inferentia-mxnet-neuron-serving.md)

# 使用 MXNet-Neuron 模型服務
<a name="tutorial-inferentia-mxnet-neuron-serving"></a>

在本教學課程中，您將學習如何使用預先培訓的 MXNet 模型來執行多模型伺服器 (MMS) 的即時影像分類。MMS 是一種靈活且易於使用的工具，可提供使用任何機器學習或深度學習架構培訓的深度學習模型。本教學課程包含使用 AWS Neuron 的編譯步驟，以及使用 MXNet 的 MMS 實作。

 如需 Neuron 開發套件的詳細資訊，請參閱 [AWS Neuron 開發套件文件](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/mxnet-neuron/index.html)。

**Topics**
+ [先決條件](#tutorial-inferentia-mxnet-neuron-serving-prerequisites)
+ [啟動 Conda 環境](#tutorial-inferentia-mxnet-neuron-serving-activate)
+ [下載範例程式碼](#tutorial-inferentia-mxnet-neuron-serving-download)
+ [編譯模型](#tutorial-inferentia-mxnet-neuron-serving-compile)
+ [執行推論](#tutorial-inferentia-mxnet-neuron-serving-inference)

## 先決條件
<a name="tutorial-inferentia-mxnet-neuron-serving-prerequisites"></a>

 在使用本教學課程之前，您應該已完成 [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md) 中的設置步驟。您也應該熟悉深度學習和使用 DLAMI。

## 啟動 Conda 環境
<a name="tutorial-inferentia-mxnet-neuron-serving-activate"></a>

 使用以下命令啟動 MXNet-Neuron conda 環境：

```
source activate aws_neuron_mxnet_p36
```

 若要退出目前的 conda 環境，請執行：

```
source deactivate
```

## 下載範例程式碼
<a name="tutorial-inferentia-mxnet-neuron-serving-download"></a>

 若要執行此範例，請使用下列命令下載範例程式碼：

```
git clone https://github.com/awslabs/multi-model-server
cd multi-model-server/examples/mxnet_vision
```

## 編譯模型
<a name="tutorial-inferentia-mxnet-neuron-serving-compile"></a>

建立一個叫做 `multi-model-server-compile.py` 的 Python 指令碼，具有以下內容。此指令碼會將 ResNet50 模型編譯至 Inferentia 裝置目標。

```
import mxnet as mx
from mxnet.contrib import neuron
import numpy as np

path='http://data.mxnet.io/models/imagenet/'
mx.test_utils.download(path+'resnet/50-layers/resnet-50-0000.params')
mx.test_utils.download(path+'resnet/50-layers/resnet-50-symbol.json')
mx.test_utils.download(path+'synset.txt')

nn_name = "resnet-50"

#Load a model
sym, args, auxs = mx.model.load_checkpoint(nn_name, 0)

#Define compilation parameters#  - input shape and dtype
inputs = {'data' : mx.nd.zeros([1,3,224,224], dtype='float32') }

# compile graph to inferentia target
csym, cargs, cauxs = neuron.compile(sym, args, auxs, inputs)

# save compiled model
mx.model.save_checkpoint(nn_name + "_compiled", 0, csym, cargs, cauxs)
```

 若要編譯模型，請使用下列命令：

```
python multi-model-server-compile.py
```

 您的輸出看起來應如以下所示：

```
...
[21:18:40] src/nnvm/legacy_json_util.cc:209: Loading symbol saved by previous version v0.8.0. Attempting to upgrade...
[21:18:40] src/nnvm/legacy_json_util.cc:217: Symbol successfully upgraded!
[21:19:00] src/operator/subgraph/build_subgraph.cc:698: start to execute partition graph.
[21:19:00] src/nnvm/legacy_json_util.cc:209: Loading symbol saved by previous version v0.8.0. Attempting to upgrade...
[21:19:00] src/nnvm/legacy_json_util.cc:217: Symbol successfully upgraded!
```

 建立一個叫做 `signature.json` 的檔案，具有以下內容，以設定輸入名稱和形狀：

```
{
  "inputs": [
    {
      "data_name": "data",
      "data_shape": [
        1,
        3,
        224,
        224
      ]
    }
  ]
}
```

您可以使用下列命令來下載 `synset.txt` 檔案。這個檔案是 ImageNet 預測類別的名稱清單。

```
curl -O https://s3.amazonaws.com/model-server/model_archive_1.0/examples/squeezenet_v1.1/synset.txt
```

按照 `model_server_template` 資料夾中的範本建立自訂服務類別。使用下列命令將範本複製到目前的工作目錄：

```
cp -r ../model_service_template/* .
```

 編輯 `mxnet_model_service.py` 模組，將 `mx.cpu()` 內容取代為 `mx.neuron()` 內容，如下所示。您還需要將 `model_input` 所使用、不必要的資料副本註釋掉，因為 MXNet-Neuron 不支援 NDArray 和 Gluon API。

```
...
self.mxnet_ctx = mx.neuron() if gpu_id is None else mx.gpu(gpu_id)
...
#model_input = [item.as_in_context(self.mxnet_ctx) for item in model_input]
```

 使用下列指令，以模型歸檔程式封裝模型：

```
cd ~/multi-model-server/examples
model-archiver --force --model-name resnet-50_compiled --model-path mxnet_vision --handler mxnet_vision_service:handle
```

## 執行推論
<a name="tutorial-inferentia-mxnet-neuron-serving-inference"></a>

啟動多模型伺服器，並使用下列命令載入使用 RESTful API 的模型。請確認 **neuron-rtd** 是以預設設定執行。

```
cd ~/multi-model-server/
multi-model-server --start --model-store examples > /dev/null # Pipe to log file if you want to keep a log of MMS
curl -v -X POST "http://localhost:8081/models?initial_workers=1&max_workers=4&synchronous=true&url=resnet-50_compiled.mar"
sleep 10 # allow sufficient time to load model
```

 以下列命令使用範例影像執行推論：

```
curl -O https://raw.githubusercontent.com/awslabs/multi-model-server/master/docs/images/kitten_small.jpg
curl -X POST http://127.0.0.1:8080/predictions/resnet-50_compiled -T kitten_small.jpg
```

 您的輸出看起來應如以下所示：

```
[
  {
    "probability": 0.6388034820556641,
    "class": "n02123045 tabby, tabby cat"
  },
  {
    "probability": 0.16900072991847992,
    "class": "n02123159 tiger cat"
  },
  {
    "probability": 0.12221276015043259,
    "class": "n02124075 Egyptian cat"
  },
  {
    "probability": 0.028706775978207588,
    "class": "n02127052 lynx, catamount"
  },
  {
    "probability": 0.01915954425930977,
    "class": "n02129604 tiger, Panthera tigris"
  }
]
```

 若要在測試之後進行清理，請透過 RESTful API 發出 delete 命令，並使用以下命令停止模型伺服器：

```
curl -X DELETE http://127.0.0.1:8081/models/resnet-50_compiled

multi-model-server --stop
```

 您應該會看到下列輸出：

```
{
  "status": "Model \"resnet-50_compiled\" unregistered"
}
Model server stopped.
Found 1 models and 1 NCGs.
Unloading 10001 (MODEL_STATUS_STARTED) :: success
Destroying NCG 1 :: success
```

# 使用 PyTorch-Neuron 和 AWS Neuron 編譯器
<a name="tutorial-inferentia-pytorch-neuron"></a>

PyTorch-Neuron 編譯 API 提供一種方法來編譯模型圖表，您可以在 AWS Inferentia 裝置上執行。

經過訓練的模型必須編譯至 Inferentia 目標，才能部署到 Inf1 執行個體上。下列教學課程編譯了 torchvision ResNet50 模型，並將其匯出為儲存的 TorchScript 模組。接著，即可使用此模型執行推論。

為了方便起見，本教學課程使用 Inf1 執行個體進行編譯和推論。實際上，您可以使用 c5 執行個體系列等其他執行個體類型來編譯模型。接著，您必須將已編譯的模型部署到 Inf1 推論伺服器。如需詳細資訊，請參閱 [AWS Neuron PyTorch SDK 文件](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/neuron-guide/neuron-frameworks/pytorch-neuron/index.html)。

**Topics**
+ [先決條件](#tutorial-inferentia-pytorch-neuron-prerequisites)
+ [啟動 Conda 環境](#tutorial-inferentia-pytorch-neuron-activate)
+ [Resnet50 編譯](#tutorial-inferentia-pytorch-neuron-compilation)
+ [ResNet50 推論](#tutorial-inferentia-pytorch-neuron-inference)

## 先決條件
<a name="tutorial-inferentia-pytorch-neuron-prerequisites"></a>

在使用本教學課程之前，您應該已完成 [使用 AWS Neuron 啟動 DLAMI 執行個體](tutorial-inferentia-launching.md) 中的設置步驟。您也應該熟悉深度學習和使用 DLAMI。

## 啟動 Conda 環境
<a name="tutorial-inferentia-pytorch-neuron-activate"></a>

使用以下命令啟動 PyTorch-Neuron conda 環境：

```
source activate aws_neuron_pytorch_p36
```

若要退出目前的 conda 環境，請執行：

```
source deactivate
```

## Resnet50 編譯
<a name="tutorial-inferentia-pytorch-neuron-compilation"></a>

建立一個叫做 **pytorch\$1trace\$1resnet50.py** 的 Python 指令碼，具有以下內容。此指令碼使用 PyTorch-Neuron 編譯 Python API 來編譯一個 ResNet-50 模型。

**注意**  
在編譯 torchvision 模型時，您應該注意的 torchvision 版本與 torch 套件之間存在相依性。這些相依性規則可以透過 pip 管理。Torchvision==0.6.1 符合 torch==1.5.1 版本，而 torchvision=0.8.2 符合 torch==1.7.1 版本。

```
import torch
import numpy as np
import os
import torch_neuron
from torchvision import models

image = torch.zeros([1, 3, 224, 224], dtype=torch.float32)

## Load a pretrained ResNet50 model
model = models.resnet50(pretrained=True)

## Tell the model we are using it for evaluation (not training)
model.eval()
model_neuron = torch.neuron.trace(model, example_inputs=[image])

## Export to saved model
model_neuron.save("resnet50_neuron.pt")
```

執行編譯指令碼。

```
python pytorch_trace_resnet50.py
```

編譯需要幾分鐘的時間。 編譯完成後，編譯的模型會儲存為本機目錄中`resnet50_neuron.pt`的 。

## ResNet50 推論
<a name="tutorial-inferentia-pytorch-neuron-inference"></a>

建立一個叫做 **pytorch\$1infer\$1resnet50.py** 的 Python 指令碼，具有以下內容。此指令碼會下載範例影像，並使用它來執行具有已編譯模型的推論。

```
import os
import time
import torch
import torch_neuron
import json
import numpy as np

from urllib import request

from torchvision import models, transforms, datasets

## Create an image directory containing a small kitten
os.makedirs("./torch_neuron_test/images", exist_ok=True)
request.urlretrieve("https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg",
                    "./torch_neuron_test/images/kitten_small.jpg")


## Fetch labels to output the top classifications
request.urlretrieve("https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json","imagenet_class_index.json")
idx2label = []

with open("imagenet_class_index.json", "r") as read_file:
    class_idx = json.load(read_file)
    idx2label = [class_idx[str(k)][1] for k in range(len(class_idx))]

## Import a sample image and normalize it into a tensor
normalize = transforms.Normalize(
    mean=[0.485, 0.456, 0.406],
    std=[0.229, 0.224, 0.225])

eval_dataset = datasets.ImageFolder(
    os.path.dirname("./torch_neuron_test/"),
    transforms.Compose([
    transforms.Resize([224, 224]),
    transforms.ToTensor(),
    normalize,
    ])
)

image, _ = eval_dataset[0]
image = torch.tensor(image.numpy()[np.newaxis, ...])

## Load model
model_neuron = torch.jit.load( 'resnet50_neuron.pt' )

## Predict
results = model_neuron( image )

# Get the top 5 results
top5_idx = results[0].sort()[1][-5:]

# Lookup and print the top 5 labels
top5_labels = [idx2label[idx] for idx in top5_idx]

print("Top 5 labels:\n {}".format(top5_labels) )
```

使用以下命令，以編譯模型執行推斷：

```
python pytorch_infer_resnet50.py
```

您的輸出看起來應如以下所示：

```
Top 5 labels:
 ['tiger', 'lynx', 'tiger_cat', 'Egyptian_cat', 'tabby']
```

# ARM64 DLAMI
<a name="tutorial-arm64"></a>

AWS ARM64 GPU DLAMIs旨在為深度學習工作負載提供高效能和成本效益。具體而言，G5g 執行個體類型具有 Arm64-based [AWS Graviton2 處理器](https://aws.amazon.com/ec2/graviton/)，該處理器由 開始建置 AWS ，並針對客戶在雲端中執行工作負載的方式進行最佳化。 AWS ARM64 GPU DLAMIs已預先設定 Docker、NVIDIA Docker、NVIDIA 驅動程式、CUDA、CuDNN、NCCL，以及 TensorFlow 和 PyTorch 等熱門機器學習架構。

透過 G5g 執行個體類型，您可以利用 Graviton2 的價格和效能優勢，與具有 GPU 加速的 x86 型執行個體相比，以顯著較低的成本部署 GPU 加速深度學習模型。

## 選取 ARM64 DLAMI
<a name="tutorial-arm64-select-dlami"></a>

使用您選擇的 ARM64 DLAMI 啟動 [G5g 執行個體](https://aws.amazon.com/ec2/instance-types/g5g/)。

如需啟動 DLAMI step-by-step說明，請參閱 [啟動和設定 DLAMI。](https://docs.aws.amazon.com/dlami/latest/devguide/launch-config.html)

如需最新的 ARM64 DLAMIs清單，請參閱 [DLAMI 的版本備註](https://docs.aws.amazon.com/dlami/latest/devguide/appendix-ami-release-notes.html)。

## 開始使用
<a name="tutorial-arm64-get-started"></a>

下列主題說明如何開始使用 ARM64 DLAMI。

**Topics**
+ [選取 ARM64 DLAMI](#tutorial-arm64-select-dlami)
+ [開始使用](#tutorial-arm64-get-started)
+ [使用 ARM64 GPU PyTorch DLAMI](tutorial-arm64-pytorch.md)

# 使用 ARM64 GPU PyTorch DLAMI
<a name="tutorial-arm64-pytorch"></a>

 AWS 深度學習 AMIs 已準備好與 Arm64 處理器型 GPUs 搭配使用，並針對 PyTorch 進行最佳化。ARM64 GPU PyTorch DLAMI 包含預先設定 [PyTorch](https://aws.amazon.com/pytorch)、[TorchVision](https://pytorch.org/vision/stable/index.html) 和 [TorchServe](https://pytorch.org/serve/) 的 Python 環境，適用於深度學習訓練和推論使用案例。

**Topics**
+ [驗證 PyTorch Python 環境](#tutorial-arm64-pytorch-environment)
+ [使用 PyTorch 執行訓練範例](#tutorial-arm64-pytorch-training)
+ [使用 PyTorch 執行推論範例](#tutorial-arm64-pytorch-inference)

## 驗證 PyTorch Python 環境
<a name="tutorial-arm64-pytorch-environment"></a>

連線至您的 G5g 執行個體，並使用下列命令啟用基本 Conda 環境：

```
source activate base
```

您的命令提示應該指出您正在基礎 Conda 環境中工作，其中包含 PyTorch、TorchVision 和其他程式庫。

```
(base) $
```

驗證 PyTorch 環境的預設工具路徑：

```
(base) $ which python
(base) $ which pip
(base) $ which conda
(base) $ which mamba
>>> import torch, torchvision
>>> torch.__version__
>>> torchvision.__version__
>>> v = torch.autograd.Variable(torch.randn(10, 3, 224, 224))
>>> v = torch.autograd.Variable(torch.randn(10, 3, 224, 224)).cuda()
>>> assert isinstance(v, torch.Tensor)
```

## 使用 PyTorch 執行訓練範例
<a name="tutorial-arm64-pytorch-training"></a>

執行範例 MNIST 訓練任務：

```
git clone https://github.com/pytorch/examples.git
cd examples/mnist
python main.py
```

您的輸出應該類似以下內容：

```
...
Train Epoch: 14 [56320/60000 (94%)]    Loss: 0.021424
Train Epoch: 14 [56960/60000 (95%)]    Loss: 0.023695
Train Epoch: 14 [57600/60000 (96%)]    Loss: 0.001973
Train Epoch: 14 [58240/60000 (97%)]    Loss: 0.007121
Train Epoch: 14 [58880/60000 (98%)]    Loss: 0.003717
Train Epoch: 14 [59520/60000 (99%)]    Loss: 0.001729
Test set: Average loss: 0.0275, Accuracy: 9916/10000 (99%)
```

## 使用 PyTorch 執行推論範例
<a name="tutorial-arm64-pytorch-inference"></a>

使用以下命令下載預先訓練的 densenet161 模型，並使用 TorchServe 執行推論：

```
# Set up TorchServe
cd $HOME
git clone https://github.com/pytorch/serve.git
mkdir -p serve/model_store
cd serve

# Download a pre-trained densenet161 model
wget https://download.pytorch.org/models/densenet161-8d451a50.pth >/dev/null

# Save the model using torch-model-archiver
torch-model-archiver --model-name densenet161 \
    --version 1.0 \
    --model-file examples/image_classifier/densenet_161/model.py \
    --serialized-file densenet161-8d451a50.pth \
    --handler image_classifier \
    --extra-files examples/image_classifier/index_to_name.json  \
    --export-path model_store 

# Start the model server
torchserve --start --no-config-snapshots \
    --model-store model_store \
    --models densenet161=densenet161.mar &> torchserve.log

# Wait for the model server to start
sleep 30

# Run a prediction request
curl http://127.0.0.1:8080/predictions/densenet161 -T examples/image_classifier/kitten.jpg
```

您的輸出應該類似以下內容：

```
{
  "tiger_cat": 0.4693363308906555,
  "tabby": 0.4633873701095581,
  "Egyptian_cat": 0.06456123292446136,
  "lynx": 0.0012828150065615773,
  "plastic_bag": 0.00023322898778133094
}
```

使用以下命令取消註冊 densenet161 模型並停止伺服器：

```
curl -X DELETE http://localhost:8081/models/densenet161/1.0
torchserve --stop
```

您的輸出應該類似以下內容：

```
{
  "status": "Model \"densenet161\" unregistered"
}
TorchServe has stopped.
```

# Inference
<a name="tutorial-inference"></a>

本節提供如何使用 DLAMI 的架構和工具執行推論的教學課程。

## 推論工具
<a name="tutorial-inference-tools"></a>
+ [TensorFlow 服務](tutorial-tfserving.md)

# 模型服務
<a name="model-serving"></a>

以下是安裝在具有 Conda 的深度學習 AMI 上的模型服務選項。按一下其中一個選項，了解如何使用它。

**Topics**
+ [TensorFlow 服務](tutorial-tfserving.md)
+ [TorchServe](tutorial-torchserve.md)

# TensorFlow 服務
<a name="tutorial-tfserving"></a>

[TensorFlow 服務](https://www.tensorflow.org/tfx/guide/serving)是提供機器學習模型的靈活、高效能服務系統。

`tensorflow-serving-api` 預先安裝了單一架構 DLAMI。若要使用張量流程服務，請先啟用 TensorFlow 環境。

```
$ source /opt/tensorflow/bin/activate
```

然後，使用您慣用的文字編輯器來建立具有下列內容的指令碼。將其命名為 `test_train_mnist.py`。此指令碼參考自 [TensorFlow 教學課程](https://github.com/tensorflow/docs/blob/master/site/en/tutorials/quickstart/beginner.ipynb)，該教學課程將訓練和評估分類影像的神經網路機器學習模型。

```
import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
```

現在執行此指令碼，將伺服器位置和連接埠以及哈士奇相片的檔案名稱當做參數傳遞。

```
$ /opt/tensorflow/bin/python3 test_train_mnist.py
```

 請耐心等待，因為指令碼可能需要一些時間才能提供輸出。訓練完成後，您應該會看到以下內容：

```
I0000 00:00:1739482012.389276    4284 device_compiler.h:188] Compiled cluster using XLA!  This line is logged at most once for the lifetime of the process.
1875/1875 [==============================] - 24s 2ms/step - loss: 0.2973 - accuracy: 0.9134 
Epoch 2/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.1422 - accuracy: 0.9582
Epoch 3/5
1875/1875 [==============================] - 3s 1ms/step - loss: 0.1076 - accuracy: 0.9687
Epoch 4/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0872 - accuracy: 0.9731
Epoch 5/5
1875/1875 [==============================] - 3s 1ms/step - loss: 0.0731 - accuracy: 0.9771
313/313 [==============================] - 0s 1ms/step - loss: 0.0749 - accuracy: 0.9780
```

## 更多功能和範例
<a name="tutorial-tfserving-project"></a>

如果您想要進一步了解 TensorFlow 服務，請參閱 [TensorFlow 網站](https://www.tensorflow.org/serving/)。

# TorchServe
<a name="tutorial-torchserve"></a>

TorchServe 是一種靈活的工具，用於提供已從 PyTorch 匯出的深度學習模型。TorchServe 已預先安裝具有 Conda 的深度學習 AMI。

如需使用 TorchServe 的詳細資訊，請參閱 [Model Server for PyTorch 文件](https://github.com/pytorch/serve/blob/master/docs/README.md)。

 **主題** 

## 在 TorchServe 上提供影像分類模型
<a name="tutorial-torchserve-serving"></a>

本教學課程說明如何使用 TorchServe 提供影像分類模型。它使用 PyTorch 提供的 DenseNet-161 模型。 一旦伺服器執行，它會監聽預測請求。當您上傳映像時，在此案例中是小貓的映像，伺服器會從訓練模型的類別中傳回前 5 個相符類別的預測。

**在 TorchServe 上提供範例影像分類模型**

1. 使用 Conda v34 或更新版本的深度學習 AMI 連線至 Amazon Elastic Compute Cloud (Amazon EC2) 執行個體。

1. 啟用環境 `pytorch_p310`。

   ```
   source activate pytorch_p310
   ```

1. 複製 TorchServe 儲存庫，然後建立目錄來存放模型。  

   ```
   git clone https://github.com/pytorch/serve.git
   mkdir model_store
   ```

1. 使用模型封存程式封存模型。`extra-files` 此參數使用來自`TorchServe`儲存庫的檔案，因此請視需要更新路徑。 如需模型封存器的詳細資訊，請參閱[適用於 TorchServe 的 Torch 模型封存器。](https://github.com/pytorch/serve/blob/master/model-archiver/README.md)

   ```
   wget https://download.pytorch.org/models/densenet161-8d451a50.pth
   torch-model-archiver --model-name densenet161 --version 1.0 --model-file ./serve/examples/image_classifier/densenet_161/model.py --serialized-file densenet161-8d451a50.pth --export-path model_store --extra-files ./serve/examples/image_classifier/index_to_name.json --handler image_classifier
   ```

1. 執行 TorchServe 以啟動端點。新增 `> /dev/null` 可靜音日誌輸出。

   ```
   torchserve --start --ncs --model-store model_store --models densenet161.mar > /dev/null
   ```

1. 下載小貓的影像並將其傳送至 TorchServe 預測端點：

   ```
   curl -O https://s3.amazonaws.com/model-server/inputs/kitten.jpg
   curl http://127.0.0.1:8080/predictions/densenet161 -T kitten.jpg
   ```

   預測端點會以類似下列前五大預測的 JSON 傳回預測，其中映像包含埃及貓的機率為 47%，接著有 46% 的機率具有 Tabby 貓。

   ```
   {
    "tiger_cat": 0.46933576464653015,
    "tabby": 0.463387668132782,
    "Egyptian_cat": 0.0645613968372345,
    "lynx": 0.0012828196631744504,
    "plastic_bag": 0.00023323058849200606
   }
   ```

1. 完成測試後，請停止伺服器：

   ```
   torchserve --stop
   ```

 **其他範例** 

TorchServe 有各種範例，您可以在 DLAMI 執行個體上執行。您可以在 [ TorchServe 專案儲存庫範例頁面上](https://github.com/pytorch/serve/tree/master/examples)檢視它們。

 **詳細資訊** 

 如需更多 TorchServe 文件，包括如何使用 Docker 設定 TorchServe 和最新的 TorchServe 功能，請參閱 GitHub 上的 [ TorchServe 專案頁面](https://github.com/pytorch/serve)。