

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

# 模型平行疑難排解
<a name="distributed-troubleshooting-model-parallel"></a>

如果遇到錯誤，可嘗試使用下列清單，對您的訓練任務進行疑難排解。如果問題持續，請聯絡 [AWS 支援](https://aws.amazon.com/premiumsupport)。

**Topics**
+ [將 SageMaker Debugger 與 SageMaker 模型平行化程式庫搭配使用的考量事項](#distributed-ts-model-parallel-debugger)
+ [儲存檢查點](#distributed-ts-model-parallel-checkpoints)
+ [使用模型平行和 TensorFlow 進行聚合](#distributed-ts-model-parallel-tf-convergence)
+ [分散式訓練任務停止或當機](#distributed-ts-model-parallel-training-issues)
+ [收到 PyTorch 訓練任務 NCCL 錯誤](#distributed-ts-model-parallel-nccl-error)
+ [收到 PyTorch 訓練任務的 `RecursionError`](#distributed-ts-model-parallel-super-forward-not-supported)

## 將 SageMaker Debugger 與 SageMaker 模型平行化程式庫搭配使用的考量事項
<a name="distributed-ts-model-parallel-debugger"></a>

SageMaker Debugger 不適用於 SageMaker 模型平行化程式庫。偵錯工具對所有 SageMaker TensorFlow 和 PyTorch 訓練任務預設為啟用，您可能會看到類似以下的錯誤：

```
FileNotFoundError: [Errno 2] No such file or directory: '/opt/ml/checkpoints/metadata.json.sagemaker-uploading
```

若要解決此問題，在建立架構 `estimator` 時按 `debugger_hook_config=False` 停用偵錯工具，如以下範例所示。

```
bucket=sagemaker.Session().default_bucket()
base_job_name="sagemaker-checkpoint-test"
checkpoint_in_bucket="checkpoints"

# The S3 URI to store the checkpoints
checkpoint_s3_bucket="s3://{}/{}/{}".format(bucket, base_job_name, checkpoint_in_bucket)

estimator = TensorFlow(
    ...

    distribution={"smdistributed": {"modelparallel": { "enabled": True }}},
    checkpoint_s3_uri=checkpoint_s3_bucket,
    checkpoint_local_path="/opt/ml/checkpoints",
    debugger_hook_config=False
)
```

## 儲存檢查點
<a name="distributed-ts-model-parallel-checkpoints"></a>

在 SageMaker AI 上儲存大型模型的檢查點時，可能會發生下列錯誤：

```
InternalServerError: We encountered an internal error. Please try again
```

這可能是由於在訓練期間將本機檢查點上傳到 Amazon S3 時，產生 SageMaker AI 限制所致。若要停用 SageMaker AI 中的檢查點，請使用下列範例明確上傳檢查點。

如果您遇到前面的錯誤，請勿與 SageMaker `estimator` 呼叫搭配使用 `checkpoint_s3_uri`。為較大的模型儲存檢查點時，我們建議將檢查點儲存到自訂目錄，並將其傳遞給輔助函式 (作為 `local_path` 引數)。

```
import os

def aws_s3_sync(source, destination):
    """aws s3 sync in quiet mode and time profile"""
    import time, subprocess
    cmd = ["aws", "s3", "sync", "--quiet", source, destination]
    print(f"Syncing files from {source} to {destination}")
    start_time = time.time()
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    p.wait()
    end_time = time.time()
    print("Time Taken to Sync: ", (end_time-start_time))
    return

def sync_local_checkpoints_to_s3(local_path="/opt/ml/checkpoints", s3_uri=os.path.dirname(os.path.dirname(os.getenv('SM_MODULE_DIR', '')))+'/checkpoints'):
    """ sample function to sync checkpoints from local path to s3 """

    import boto3
    #check if local path exists
    if not os.path.exists(local_path):
        raise RuntimeError("Provided local path {local_path} does not exist. Please check")

    #check if s3 bucket exists
    s3 = boto3.resource('s3')
    if not s3_uri.startswith("s3://"):
        raise ValueError(f"Provided s3 uri {s3_uri} is not valid.")

    s3_bucket = s3_uri.replace('s3://','').split('/')[0]
    print(f"S3 Bucket: {s3_bucket}")
    try:
        s3.meta.client.head_bucket(Bucket=s3_bucket)
    except Exception as e:
        raise e
    aws_s3_sync(local_path, s3_uri)
    return

def sync_s3_checkpoints_to_local(local_path="/opt/ml/checkpoints", s3_uri=os.path.dirname(os.path.dirname(os.getenv('SM_MODULE_DIR', '')))+'/checkpoints'):
    """ sample function to sync checkpoints from s3 to local path """

    import boto3
    #try to create local path if it does not exist
    if not os.path.exists(local_path):
        print(f"Provided local path {local_path} does not exist. Creating...")
        try:
            os.makedirs(local_path)
        except Exception as e:
            raise RuntimeError(f"Failed to create {local_path}")

    #check if s3 bucket exists
    s3 = boto3.resource('s3')
    if not s3_uri.startswith("s3://"):
        raise ValueError(f"Provided s3 uri {s3_uri} is not valid.")

    s3_bucket = s3_uri.replace('s3://','').split('/')[0]
    print(f"S3 Bucket: {s3_bucket}")
    try:
        s3.meta.client.head_bucket(Bucket=s3_bucket)
    except Exception as e:
        raise e
    aws_s3_sync(s3_uri, local_path)
    return
```

輔助函式的用法：

```
#base_s3_uri - user input s3 uri or save to model directory (default)
#curr_host - to save checkpoints of current host
#iteration - current step/epoch during which checkpoint is saved

# save checkpoints on every node using local_rank
if smp.local_rank() == 0:
    base_s3_uri = os.path.dirname(os.path.dirname(os.getenv('SM_MODULE_DIR', '')))
    curr_host = os.environ['SM_CURRENT_HOST']
    full_s3_uri = f'{base_s3_uri}/checkpoints/{curr_host}/{iteration}'
    sync_local_checkpoints_to_s3(local_path=checkpoint_dir, s3_uri=full_s3_uri)
```

## 使用模型平行和 TensorFlow 進行聚合
<a name="distributed-ts-model-parallel-tf-convergence"></a>

將 SageMaker AI 多節點訓練與 TensorFlow 和模型平行化程式庫搭配使用時，遺失可能無法如預期般聚合，因為每個節點上的訓練輸入檔案順序可能不同。這可能會導致同一模型平行群組中的不同排名處理不同的輸入檔案，進而導致不一致。為防止此情況發生，請確保輸入檔案轉換為 TensorFlow 資料集之前，在所有排名中都以相同的方式排序。達成此目標的一種方法是在訓練指令碼中對輸入檔案名稱進行排序。

## 分散式訓練任務停止或當機
<a name="distributed-ts-model-parallel-training-issues"></a>

如果您的訓練任務停止、當機或沒有回應，請閱讀下列疑難排解項目以找出問題的原因。如果您需要任何進一步支援，請透過 [AWS 支援](https://aws.amazon.com/premiumsupport)與 SageMaker 分散式訓練團隊聯絡。
+  如果您**在 NCCL 初始化步驟中看到分散式訓練任務停止**，請考慮下列事項：
  + 如果您將其中一個已啟用 EFA 的執行個體 (`ml.p4d` 或 `ml.p3dn` 執行個體) 與自訂 VPC 及其子網路搭配使用，請確保所使用的安全群組具有往返相同 SG 的所有連接埠的傳入和傳出連線。通常，您還需要對任何 IP 的傳出連線做為單獨規則 (用於可存取的網際網路)。若要尋找如何針對 EFA 通訊新增傳入和傳出規則的指示，請參閱[初始化期間的 SageMaker AI 分散式訓練任務停滯](distributed-troubleshooting-data-parallel.md#distributed-ts-data-parallel-efa-sg)。
+ 如果您在**建立完整模型檢查點時看到分散式訓練任務停止**，這可能是因為模型或最佳化工具上的 `state_dict()` 呼叫並非以 `rdp_rank()==0` (使用張量平行處理時) 或 `dp_rank()==0` (僅使用管道平行處理時) 在所有排名上進行。這些排名需要溝通來建構要儲存的檢查點。如果啟用 `shard_optimizer_state`，在建立部分最佳化工具檢查點時，也可能發生類似的停止問題。

  如需在以模型平行化的模型建立檢查點的詳細資訊，請參閱[儲存與載入的一般指示](https://sagemaker.readthedocs.io/en/v2.199.0/api/training/smp_versions/latest/smd_model_parallel_pytorch.html#general-instruction-for-saving-and-loading)和 [對分散式 PyTorch 模型執行檢查點 (適用於 1.6.0 版和 1.9.0 版之間的 SageMaker 模型平行處理程式庫)](distributed-model-parallel-checkpointing-and-finetuning.md#model-parallel-extended-features-pytorch-saving-loading-checkpoints)。
+ 如果訓練任務因 **CUDA 記憶體不足錯誤**而當機，這表示需要調整分散式訓練組態，以符合 GPU 叢集上的模型。如需更多資訊和最佳實務，請參閱[為指定的模型設定正確組態](model-parallel-best-practices.md#model-parallel-best-practices-configuration)。
+ 如果訓練工作因**無法修正的 [ECC 錯誤](https://docs.nvidia.com/deploy/a100-gpu-mem-error-mgmt/index.html)**而當機，這表示叢集中的其中一個 GPU 已經壞了。如果您需要技術支援，請與 AWS 團隊共享任務 ARN，並在可能的情況下從檢查點重新啟動訓練任務。
+ 在極少數情況下，先前運作但接近 GPU 記憶體限制的任務組態可能會因為 **CUDA 記憶體不足錯誤**而在不同的叢集中失敗。這可能是因為由於 ECC 錯誤，某些 GPU 的可用記憶體比平常低。
+ 執行未使用節點中所有 GPU 的多節點工作時，可能會發生**網路逾時當機**。若要解決此問題，請確定 `processes_per_host` 參數設定為每個執行個體中的 GPU 數量，以使用節點上的所有 GPU。例如，這是用於 `ml.p3.16xlarge`、`ml.p3dn.24xlarge` 和 `ml.p4d.24xlarge` 執行個體的 `processes_per_host=8`。
+ 如果您發現訓練任務在資料下載階段需要很長時間，請確保您為 SageMaker `Estimator` 類別的 `checkpoint_s3_uri` 提供的 Amazon S3 目前訓練任務的唯一路徑。如果在同時執行的多個訓練任務中重複使用此路徑，則所有這些檢查點都會上傳和下載到相同的 Amazon S3 路徑，並可能大幅增加檢查點載入時間。
+ 處理大型資料和模型時，請使用 FSx for Lustre。
  + 如果您的資料集很大且擷取需要很長時間，我們建議您將資料集保留在 [FSx for Lustre](https://aws.amazon.com/fsx/lustre/) 中。
  + 訓練模型超過 100 億個參數時，我們建議使用 FSx for Lustre 建立檢查點。
  + 建立檔案系統之後，請務必等待狀態變為**可用**，再開始使用該檔案系統的訓練任務。

## 收到 PyTorch 訓練任務 NCCL 錯誤
<a name="distributed-ts-model-parallel-nccl-error"></a>

如果遇到下列錯誤，可能是由於處理耗盡 GPU 記憶體。

```
NCCL error in: ../torch/lib/c10d/ProcessGroupNCCL.cpp:825, unhandled system error, NCCL version 2.7.8
ncclSystemError: System call (socket, malloc, munmap, etc) failed.
```

您可以透過減少批次大小或 `active_microbatches` 來解決此問題。如果自動分割無法產生良好的平衡分割，您可能需要考慮手動分割。如需詳細資訊，請參閱[跨節點的管道平行處理](model-parallel-best-practices.md#model-parallel-best-practices-configuration-pipeline-across-nodes)。

## 收到 PyTorch 訓練任務的 `RecursionError`
<a name="distributed-ts-model-parallel-super-forward-not-supported"></a>

該程式庫不支援在模組的正向呼叫內呼叫 `super.forward()`。如果您使用 `super.forward()`，可能會收到下列錯誤訊息。

```
RecursionError: maximum recursion depth exceeded
```

若要修復錯誤，您應呼叫 `super()._orig_forward()` 而不是呼叫 `super.forward()`。