HorovodRunner:使用 Horovod 的分散式深度學習
重要
Horovod 和 HorovodRunner 現在已被取代。 15.4 LTS ML 之後的版本將不會預安裝此套件。 針對分散式深度學習,Databricks 建議搭配使用 TorchDistributor 與 PyTorch 進行分散式訓練,或搭配使用 tf.distribute.Strategy
API 與 TensorFlow 進行分散式訓練。
了解如何使用 HorovodRunner 來執行機器學習模型的分散式訓練,在 Azure Databricks 上將 Horovod 訓練作業作為 Spark 作業啟動。
何謂 HorovodRunner?
HorovodRunner 是一般 API,可使用 Horovod 架構在 Azure Databricks 上執行分散式深度學習工作負載。 透過整合 Horovod 與 Spark 的屏障模式,Azure Databricks 能夠針對 Spark 上長時間執行的深度學習訓練作業提供更高的穩定性。 HorovodRunner 採用 Python 方法,其中包含具有 Horovod 勾點的深度學習訓練程式碼。 HorovodRunner 會在驅動程式中挑選方法,並將其散發給 Spark 背景工作角色。 Horovod MPI 作業會內嵌為使用屏障執行模式的 Spark 作業。 第一個執行程式會使用 BarrierTaskContext
收集所有任務執行程式的 IP 位址,並使用 mpirun
觸發 Horovod 作業。 每個 Python MPI 過程都會載入挑選好的使用者程式,將其還原序列化並加以執行。
使用 HorovodRunner 的分散式訓練
HorovodRunner 可讓您啟動 Horovod 訓練作業作為 Spark 作業。 HorovodRunner API 支援資料表中顯示的方法。 如需詳細資訊,請參閱 HorovodRunner API 文件。
方法和簽名 | 描述 |
---|---|
init(self, np) |
建立 HorovodRunner 的執行個體。 |
run(self, main, **kwargs) |
執行叫用 main(**kwargs) 的 Horovod 訓練作業。 主函數和關鍵字引數會使用 cloudpickle 序列化,並散發給叢集背景工作角色。 |
使用 HorovodRunner 開發分散式訓練計劃的一般方法是:
- 建立以節點數目初始化的
HorovodRunner
執行個體。 - 根據 Horovod 使用方式中所述的方法定義 Horovod 訓練方法,請務必在方法內新增任何匯入陳述式。
- 將訓練方法傳遞至
HorovodRunner
執行個體。
例如:
hr = HorovodRunner(np=2)
def train():
import tensorflow as tf
hvd.init()
hr.run(train)
若只在驅動程式上使用 n
子流程執行 HorovodRunner,請使用 hr = HorovodRunner(np=-n)
。 例如,如果驅動程式節點上有 4 個 GPU,可以選擇 n
到 4
。 如需有關參數 np
的詳細資訊,請參閱 HorovodRunner API 文件。 如需有關如何為每個子流程固定一個 GPU 的詳細資訊,請參閱 Horovod 使用指南。
常見的錯誤是無法找到或挑選 TensorFlow 物件。 當程式庫匯入陳述式未散發至其他執行程式時,就會發生這種情況。 若要避免此問題,請在 Horovod 訓練方法頂端以及 Horovod 訓練方法中呼叫的任何其他使用者定義的函數內,包含所有匯入陳述式 (例如 import tensorflow as tf
)。
使用 Horovod Timeline 記錄 Horovod 訓練
Horovod 能夠記錄其活動的時間表,稱為 Horovod Timeline。
重要
Horovod Timeline 會對效能產生重大影響。 啟用 Horovod Timeline 時,Inception3 輸送量可能會減少約 40%。 若要加速 HorovodRunner 作業,請勿使用 Horovod Timeline。
在進行訓練時,無法檢視 Horovod Timeline。
若要記錄 Horovod Timeline,請將 HOROVOD_TIMELINE
環境變數設定為您要儲存時程表檔案的位置。 Databricks 建議使用共用儲存體中的位置,以便可輕鬆地擷取時間表檔案。 例如,您可以使用 DBFS 本機檔案 API,如下所示:
timeline_dir = "/dbfs/ml/horovod-timeline/%s" % uuid.uuid4()
os.makedirs(timeline_dir)
os.environ['HOROVOD_TIMELINE'] = timeline_dir + "/horovod_timeline.json"
hr = HorovodRunner(np=4)
hr.run(run_training_horovod, params=params)
然後,將時間表特定程式碼新增至訓練函數的開頭和結尾。 下列範例筆記本包含範例程式碼,可用來作為檢視訓練進度的因應措施。
Horovod 時間表範例筆記本
若要下載時間表檔案,請使用 Databricks CLI,然後使用 Chrome 瀏覽器的 chrome://tracing
功能來檢視它。 例如:
開發工作流程
這些是將單一節點深度學習程式碼移轉至分散式訓練的一般步驟。 本節中的範例:使用 HorovodRunner 移轉至分散式深度學習將說明這些步驟。
- 準備單一節點程式碼:使用 TensorFlow、Keras 或 PyTorch 來準備及測試單一節點程式碼。
- 移轉至 Horovod:遵循 Horovod 使用方式中的指示,使用 Horovod 來移轉程式碼,並在驅動程式上進行測試:
- 新增
hvd.init()
以初始化 Horovod。 - 使用
config.gpu_options.visible_device_list
透過此程序來固定要使用的伺服器 GPU。 透過每個程序一個 GPU 的一般設定,可以設定為本機排名。 在此情況下,伺服器上的第一個程序將會被配置第一個 GPU,第二個程序將會被配置第二個 GPU,以此類推。 - 包含資料集的分區。 執行分散式訓練時,此資料集運算子非常有用,因為它可讓每個背景工作角色讀取唯一的子集。
- 依背景工作角色數目調整學習率。 同步分散式訓練中的有效批次大小會依背景工作角色數目進行調整。 提高學習率可補償批次大小的增加。
- 將最佳化工具包裝在
hvd.DistributedOptimizer
中。 分散式最佳化工具會將梯度計算委派給原始最佳化工具,使用 allreduce 或 allgather 對梯度進行平均,然後套用平均梯度。 - 新增
hvd.BroadcastGlobalVariablesHook(0)
以將初始變數狀態從排名 0 廣播到所有其他程序。 在使用隨機加權或從檢查點還原定型時,需要確保所有背景工作角色的初始化一致。 或者,如果您不使用MonitoredTrainingSession
,可以在全域變數初始化之後執行hvd.broadcast_global_variables
操作。 - 修改您的程式碼,只儲存背景工作角色 0 上的檢查點,以防止其他背景工作角色損毀它們。
- 新增
- 移轉至 HorovodRunner:HorovodRunner 會叫用 Python 函數來執行 Horovod 訓練作業。 必須將主要的訓練程序包裝到單一 Python 函數中。 然後,可以在本機模式和分散式模式中測試 HorovodRunner。
更新深度學習庫
如果您升級或降級 TensorFlow、Keras 或 PyTorch,則必須重新安裝 Horovod,才能針對新安裝的庫進行編譯。 例如,如果您想要升級 TensorFlow,Databricks 建議使用 TensorFlow 安裝指示中的 init 指令碼,並將下列 TensorFlow 特定 Horovod 安裝程式碼附加至它的結尾。 請參閱 Horovod 安裝指示,以使用不同的組合,例如升級或降級 PyTorch 和其他庫。
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt update
# Using the same compiler that TensorFlow was built to compile Horovod
apt install g++-7 -y
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60
HOROVOD_GPU_ALLREDUCE=NCCL HOROVOD_CUDA_HOME=/usr/local/cuda pip install horovod==0.18.1 --force-reinstall --no-deps --no-cache-dir
範例:使用 HorovodRunner 移轉至分散式深度學習
下列範例會根據 MNIST 資料集,示範如何使用 HorovodRunner 將單一節點深度學習程式移轉至分散式深度學習。
限制
- 使用工作區檔案時,如果
np
設定為大於 1 且筆記本會從其他相對檔案匯入,HorovodRunner 將無法運作。 請考慮使用 horovod.spark 而非HorovodRunner
。 - 如果遇到類似
WARNING: Open MPI accepted a TCP connection from what appears to be a another Open MPI process but cannot find a corresponding process entry for that peer
的錯誤,這表示叢集中節點之間的網路通訊發生問題。 若要解決此錯誤,請在訓練程式碼中新增下列片段,以使用主要網路介面。
import os
os.environ["OMPI_MCA_btl_tcp_if_include"]="eth0"
os.environ["NCCL_SOCKET_IFNAME"]="eth0"