GPU 加速的 Apache Spark 3

Spark 3 和 GPU

由於許多資料處理工作具備平行的特性,因此 GPU 的大規模平行架構自然能夠進行平行化並加速 Spark 資料處理查詢,就如同 GPU 加速人工智慧 (AI) 中的深度學習 (DL)。因此,NVIDIA® 與 Spark 社群攜手合作,在 Spark 3.x 中執行 GPU 加速。 

雖然 Spark 以分割區的形式在節點之間分配運算,但一直以來,分割區內的運算都是在 CPU 核心上進行。然而,在 Spark 中 GPU 加速的好處不勝枚舉。首先,伺服器的需求數量減少,可降低基礎架構成本。而且,由於查詢完成速度更快,取得結果的時間亦會縮短。此外,由於 GPU 加速是透明的,專為在 Spark 上執行所打造的應用程式無需更改,就可享有 GPU 加速帶來的效益。

Spark 中的加速 ETL 和人工智慧

隨著機器學習 (ML) 和深度學習 (DL) 越來越常應用於較大型的資料集,Spark 已成為資料前置處理及特徵工程的常用工具,這兩項為學習階段準備原始輸入資料所需的作業。Spark 社群一直致力於將此端對端流程的兩個階段整合在一起,讓資料科學家能夠只處理單一 Spark 叢集,也可避免資料在階段間透過外部資料湖轉換的問題。Uber 推出的 Horovod 和 Yahoo 推出的 TensorFlowOnSpark 即是運用此方法的例子。

Spark 3.x 是重要的里程碑,因為現在 Spark 可以在採用 GPU 的 Spark 叢集上,為 GPU 加速的機器學習和深度學習應用程式排程。完整的 Spark 3 軟體堆疊 (包括適用於 Apache Spark 的 RAPIDS 加速器) 如下圖所示。

NVIDIA CUDA 上的全新 GPU 加速函式庫

如前所述,NVIDIA® CUDA® 是一種程式設計模型和一組 API,用於加速 NVIDIA GPU 架構上的作業。RAPIDS 建構於 CUDA 分層之上,是開放原始碼軟體庫和 API 套件,透過 DataFrame 和圖形作業提供 GPU 平行處理和高頻寬記憶體速度。

RAPIDS GPU 加速的 Spark DataFrame

RAPIDS 根據 Apache Arrow 資料結構提供強大的 GPU DataFrame。Arrow 制定了標準化、跨語言並針對資料區域最佳化的欄式記憶體格式,加速現代 CPU 或 GPU 的分析處理效能。透過 GPU DataFrame,來自多個記錄的列值批次利用現代 GPU 設計,加快讀取、查詢和寫入速度。    

Spark GPU 加速的 DataFrame 和 SQL

在 Apache Spark 3.0 中,Spark SQL 與 DataFrame 使用全新的 RAPIDS API,進行 GPU 加速記憶體高效列資料處理和查詢計畫。透過 RAPIDS 加速器,Catalyst 查詢最佳化外掛介面便能進一步延伸至查詢計畫中,識別出可透過 RAPIDS API (主要是一對一對應) 加速的運算子 (operator),並於執行查詢計畫時在 Spark 叢集中的 GPU 上排程這些運算子。

透過 CPU 的實體計畫,DataFrame 資料會轉換為 RDD 列格式,且通常一次處理一列。Spark 支援欄式批次,但在 Spark 2.x 中,只有向量化 Parquet 和 ORC 讀取器使用它。RAPIDS 外掛程式將 GPU 上的欄式批次處理延伸至大部分的 Spark 作業。對於 GPU 來說,處理欄式資料比逐列處理更加容易方便。

建立在 OpenUCX 通訊函式庫基礎上的全新 Spark 隨機變換 (shuffle) 實作,利用 NVLink、RDMA 和 InfiniBand (如果可用),透過以下方式大幅減少 Spark 流程中的資料傳輸:盡可能將資料保留在 GPU 上、充分利用可用的硬體資源,尋找在節點之間移動資料的最快路徑,包括繞過 CPU 進行 GPU 對 GPU 記憶體節點內和節點之間進行傳輸。  RDMA 允許 GPU 以 PCIe 速度直接在節點中傳輸資料,就像在大型伺服器上般運作。  NVLink 允許 GPU 以高達每秒 300 GB 的速度啟動點對點通訊。

Spark 中的 GPU-Aware 排程

Spark 3.x 加入了與 YARN、Kubernetes 和 Standalone 叢集管理器的整合,以要求 GPU 和外掛點,這些點可延伸至 GPU 上執行作業。對於 Kubernetes,Spark 3.x 在執行程式 pod 級別上提供 GPU 隔離。因此 Spark 應用程式開發人員能更輕鬆地要求並使用 GPU,還能與深度學習及人工智慧框架 (如 Spark 上的 Horovod 及 TensorFlow) 更為緊密整合,更加有效地利用 GPU。 

下圖顯示 GPU 排程流程的範例。使用者提交帶有 GPU 資源設定探索指令碼的應用程式。Spark 啟動驅動程式,該驅動程式使用配置傳遞給叢集管理員,要求具有指定資源量和 GPU 的容器。叢集管理員傳回容器。Spark 啟動容器。當執行程式開始時,會執行探索指令碼。Spark 將這些資訊發送回驅動程式,然後驅動程式可使用這些資訊將任務排程給 GPU。 

Spark Web UI 已經過修改,增加了新的核取方塊來查看哪些資源已被分配。在這個範例中,已分配了兩個 GPU。

Spark 3.x 階段級資源排程讓您可以為不同階段選擇不同的容器大小。例如,一個用於 ETL,另一個用於機器學習。

XGBoost、RAPIDS、及 Spark

XGBoost 是可擴充的分散式梯度提升決策樹 (GBDT) 機器學習函式庫。XGBoost 提供的平行決策樹提升,是處理迴歸、分類和排序問題的主要機器學習函式庫。RAPIDS 團隊與 Distributed Machine Learning Common (DMLC) XGBoost 組織密切合作,現在 XGBoost 已加入了流暢的拖曳式 (drop-in) GPU 加速,能顯著加速模型訓練並提高預測準確性。

RAPIDS、XGBOOST 和 SPARK 具有三個功能,有助於加快速度和節省成本:

  • GPU 加速的 DataFrame:將支援輸入的檔案格式直接讀入 GPU 記憶體,無論其數量及大小,並在不同的訓練節點之間平均區分。

  • GPU 加速訓練:XGBoost 訓練時間已透過訓練資料的動態記憶體內表示法而有所改善,可根據資料集的稀少度以最佳方式儲存特徵。這種方式取代了透過不同訓練實例以取得最多特徵的固定記憶體內表示法。

  • 高效使用 GPU 記憶體:XGBoost 要求資料須符合記憶體,因此對使用單一 GPU 或分散式多 GPU 多節點訓練的資料大小產生限制。最新版本將 GPU 記憶體利用率提高 5 倍。現在,使用者可使用比第一個版本大 5 倍的資料進行訓練。這種方式能改善訓練的總成本,但不影響效能。

在此電子書的後半段,我們會探討和討論使用升級的 XGBoost 函式庫來載入/轉換資料並使用 GPU 進行分散式訓練的範例。

其他 Spark 3.x 功能

  • 適應性查詢執行:Spark 2.2 將成本型最佳化加入現有的規則型 SQL 最佳化工具中。現在 Spark 3.0 已具有執行階段適應性查詢執行 (AQE)。透過 AQE,便可運用從已完成查詢計畫階段取得的執行階段統計資料,重新將其餘查詢階段的執行計畫最佳化。根據 Databricks 基準測試顯示,使用 AQE 時,加速效果提升了 1.1 倍到 8 倍。

    Spark 3.0 AQE 最佳化功能包括:

    • 動態合併隨機變換分割區:AQE 可以查看隨機變換檔案統計資料,將相鄰的小型分割區合併成較大的分割區,以減少查詢彙總的工作數量。
    • 動態切換聯結策略:AQE 可以根據聯結關係大小,在執行階段將聯結策略最佳化。例如將排序合併聯結 (sort merge join) 轉換成廣播雜湊聯結 (broadcast hash join),如果聯結的一側小到可以置入記憶體時,執行的效能便會更好。
    • 動態最佳化扭曲聯結:AQE 可以使用執行階段統計資料,偵測排序合併聯結分割區大小中的資料扭曲,並將扭曲分割區分成較小的子分割區。
  • 動態分割區剪除 (Pruning):分割區剪除是一種效能最佳化的方式,可限制 Spark 在查詢時讀取的檔案和分割區的數量。分割資料後,僅允許 Spark 讀取目錄和檔案之子集,以查詢符合分割區篩選條件的的方式提高效能。透過 Spark 3.0 動態分割區剪除,Spark 引擎可透過識別在聯結中篩選另一個表格所產生的分割區欄值,在執行階段動態推斷表格中需要讀取和處理的特定分割區,以進行特定查詢。例如,以下查詢牽涉兩個表格:包含所有航班總銷售額的 flight_sales 表格 (按出發機場劃分) 和包含每個區域機場地圖的 flight_airports 表格。我們想查詢東北美洲地區的銷售情況。

select fs.airport, fs.total_sales
from flight_sales fs, flight_airports fa
where fs.airport = fa.airport and fa.region  ='NEUSA’

透過動態分割區剪除,此查詢僅掃描和處理符合區域篩選條件的機場分割區。減少讀取和處理的資料量,可大幅節省時間。

  • 聯結策略提示會指示最佳化工具為聯結策略使用提示計畫。將 MERGE、SHUFFLE_HASH 和 SHUFFLE_REPLICATE_NL 提示加入至現有的廣播提示中。
  • DataSource API 改善:
    • 插入式目錄整合。
    • 透過減少資料載入,改善謂詞下推 (predicate push down) 來提升查詢速度。

摘要

在這一章中,我們涵蓋了 Spark 3.x 的主要改善部分,這些改善加速了取得見解的時間,特別是在 NVIDIA GPU 上執行的情況下。關於全新 Spark 3.0 功能細節可參考 Spark 3.0 發布說明