技術解讀:英特爾 x86 平臺上,AI 能力是如何進行演進的?(附PPT)

OpenAnolis小助手發表於2022-03-14

AI 計算力的指數增長意味著,為了解決越來越複雜的用例,即使是 1000 倍的計算效能增長也很容易被消耗。因此,需要透過軟體生態系統的助力,才能達到更好的效能。 我們相信,構建 AI 軟體生態系統,是將人工智慧和資料科學專案推向生產的關鍵。 本文整理自 龍蜥大講堂技術直播第四期 龍蜥社群AI SIG核心成員、英特爾 AI 軟體開發⼯程師黃文歡 分享——用技術和例項講解英特爾 x86 平臺 AI 能力演進的關鍵。

以下是本期龍蜥大講堂技術直播回顧文:

人工智慧的發展為社會各個領域帶來了無限可能,但這些應用都需要很強的計算效能和最佳化來提供準確、及時的結果。人工智慧模型複雜性的增長速度是飛速的,大約三年前,像 ELMo 這樣的自然語言模型只有 9400 萬個引數,而今年最大的模型達到了超過 1 萬億個引數。

一、英特爾 x86 平臺 AI 能力演進

自 Skylake 以來,英特爾透過從 AVX256 升級到 AVX512,將 AVX 的能力提高了一倍,這極大地提高了深度學習訓練和推理能力。一年後,在 Cascade Lake 中引入 DL Boost VNNI,大大提高 INT8 乘加吞吐量。自 Cooper Lake 之後,英特爾將BFloat16(BF16) 新增到 DL Boost 指令集中,以進一步提高深度學習訓練和推理效能。硬體一直在向前發展,AMX 自 Sapphire Rapids 開始推出,將會進一步提高 VNNI 和 BF16 從 1 維-向量到 2 維-矩陣的能力。英特爾可擴充套件處理器透過英特爾Deep Learning Boost (Intel ®DL Boost) 將嵌入式 AI 效能提升到一個新的水平。英特爾的 Deep Learning Boost ( DL Boost ) 是 x86-64 上指令集架構功能的名稱,旨在提高深度學習任務(例如訓練和推理)的效能。DL Boost 包含兩組關鍵技術:

  • AVX-512 VNNI:主要用於卷積神經網路的快速乘法累加。

  • AVX-512 BF16:用於更快計算的低精度 BFloat16 浮點數。

圖1. 英特爾x86平臺AI能力演進


Intel ® DL Boost – VNNI

英特爾深度學習加速包括 AVX512 VNNI,VNNI 代表向量神經網路指令,是對標準英特爾指令集 AVX512 的擴充套件。AVX512 VNNI 旨在加速基於卷積神經網路的演算法。AVX512 透過引入 4 個新指令加快內部卷積神經網路環路。AVX512 VNNI 擴充套件背後的主要動機是觀察到許多緊密的迴圈需要兩個 16 位值或兩個 8 位值的重複乘法,並將結果累加到 32 位累加器。

圖2. 利用基礎AVX 512 vs. 利用AVX512 VNNI 做向量乘加

深度學習的核心計算可以簡化為乘加運算。在 VNNI 之前,我們需要做圖 1 中這樣的向量乘加,使用基礎 AVX-512,對於 16 位,這可以使用兩條指令實現 VPMADDWD用於將兩個 16 位對相乘並將它們加在一起,然後將 VPADDD 新增累加值。利用基礎 AVX512 需要 3 條指令,而 VNNI 只需要 1 個週期就可以完成。透過將三條指令融合為一條,可以最大化利用計算資源,提升 cache 利用率及避免潛在的頻寬瓶頸。因此,在這個意義上,VNNI 透過與非 VNNI 比較,將為 INT8 帶來 3x 峰值計算的提升。此外,由於在一個 AVX512 暫存器中,與 FP32 相比可以容納 4 倍 INT8 資料,如果與 FP32 相比又可以帶來 4x 峰值計算的提升。
Intel ® DL Boost – BFloat16

BFloat16(BF16) 主要思想是提供 16 位浮點格式,其動態範圍與標準 IEEE-FP32 相同,但精度較 FP32 變低。相當於指數區和 FP32 保持了相同的 8 位,並將 FP32 分數字段的小數區縮減到到了 7 位。大多數情況下,使用者在進行神經網路計算時,BF16 格式與 FP32 一樣準確,但是以一半的位數完成任務。因此,與 32 位相比,採用 BF16 吞吐量可以翻倍,記憶體需求可以減半。此外,fp32 到 bf16 的轉化,相對於 fp32 到 fp16 的轉化更加簡單。

圖3. BFloat16資料型別介紹
英特爾 ® 深度學習加速技術包括以下 BFloat16 指令:

二、英特爾AI 軟體開發及部署生態系統

隨著 AI 應用在視覺、語音、推薦系統等方面不斷增長和多樣化,英特爾的目標是提供一套優越的 AI 開發和部署生態系統,使每個開發人員、資料科學家、研究人員和資料工程師儘可能無縫使用,以加快他們從邊緣到雲端的 AI 之旅。對於所有硬體和軟體最佳化以及模型量化演算法,我們需要了解它們以更好地利用,為了使每個使用者都可以便捷使用這些最佳化,英特爾提供了一套自頂向下的全棧 AI 軟體系統。對於不同需求的工程師,都可以在英特爾 AI 軟體生態系統中找到適合他們的應用。對於想要開發自己的高效能應用程式或庫的深度開發人員,可以直接呼叫相關的指令。對於想要擺脫框架開銷的框架開發人員或 AI工程師,你可以直接使用 OneDNN。對於那些已經擁有 TensorFlow/PyTorch 等 AI 框架訓練的模型的人來說,Intel 已經將大部分補丁上流到開源中,直接使用它們並享受效能,或者進一步使用英特爾對於這些框架的擴充套件最佳化。對於那些想要追求更多特定 推理的最佳化的人,可以使用 INC 工具庫。
2.1 深度神經網路庫 OneDNN

oneDNN 是一個開源的跨平臺高效能庫,包含用於深度學習應用程式的基本構建模組。基於英特爾平臺,oneDNN 對深度神經網路進行 op 級以及指令集級的最佳化。

  • 幫助開發人員建立高效能深度學習框架

  • 相同的 API 為英特爾 cpu 和 gpu,使用最好的技術來完成這項工作

  • 支援 Linux、Windows 和 macOS

該底層庫圍繞四個概念建立:
1.原語(Primitive): 是一個封裝了特定計算過程的函式物件,特定計算過程如前向卷積,LSTM 反向計算等。可以透過原語的屬性來控制原語表達更復雜的融合操作,例如前向卷積和 ReLU 的融合。這裡需要注意的是建立原語是重量級操作,最好的方式是一次建立、重複使用。或者可以透過快取具有相同引數的原語來減少原語建立成本。
2.引擎(Engine): 是計算裝置的抽象,包括 CPU,特定 GPU 卡等。建立的大多數原語是在一個特定引擎上執行計算,引擎類似於異構計算的 host 和 device 概念的統一,是可執行計算的裝置的抽象。
3.流(Stream): 是繫結到特定引擎的執行上下文的封裝。
4.記憶體物件 (memory):  封裝了分配給特定引擎的記憶體控制程式碼、 tensor 的維度、資料型別、資料排布等資訊。記憶體物件在執行期間被傳遞給原語進行處理。可以透過記憶體描述符 (memory::desc) 建立記憶體物件。

圖4. OneDNN 關係圖
優勢:

  • 支援關鍵資料型別:float32、float16、bfloat16 和 int8

  • 實現了豐富的操作:convolution, matrix multiplication, pooling, batch normalization, activation functions, recurrent neural network (RNN) cells, and long short-term memory (LSTM) cells

  • 支援自動檢測硬體指令,提高神經網路在指定硬體,特別是英特爾 CPU 和 GPU 上的執行速度。

2.2 最佳化深度學習框架:TensorFlow, PyTorch
深度學習框架透過高階程式設計介面為資料科學家、AI開發人員和研究人員提供模組,以構建、訓練、驗證和部署模型。
英特爾透過 oneDNN 庫進行的軟體最佳化為幾個流行的深度學習框架帶來了數量級的效能提升,而且大多數最佳化已經上傳到預設框架分發版中。但是,對於 TensorFlow 和 PyTorch,我們還維護單獨的 Intel 擴充套件作為尚未上傳的最佳化的緩衝區。
2.2.1 Intel ® Optimization for TensorFlow*
英特爾對於 TensorFlow 的最佳化主要包括以下三個方面:
1)在運算元最佳化部分, 將預設的(Eigen)核心替換為(使用oneDNN)高度最佳化的核心,OneDNN最佳化了一系列TensorFlow操作。OneDNN 庫是開源的,在構建 TensorFlow時自動下載。
2)在圖最佳化方面, 圖最佳化主要是希望在不影響模型的數值特性的基礎上,透過圖變換達到簡化計算、資源開銷,提升效能,所以是效能最佳化時的首選方法之一。Intel® Optimization for TensorFlow*中所做的圖最佳化包括運算元融合及佈局傳播。

  • 運算元融合

運算元融合是一個 常見的效能最佳化方法,在融合之前,每個運算元計算前後都需要把資料從記憶體讀到快取,再從快取寫回到記憶體。 而融合之後,可以避免運算元之間記憶體讀寫從而提高效能。
圖5. 運算元融合
所以在做運算元融合的時候本質上便是把多個 Tensor 整合到一個 Node 下。 雖然只是簡單的運算元融合,但是在計算過程中可以提高速度。

  • 佈局傳播

在佈局傳播方面,資料佈局是會很大程度影響效能的,因此,我們需要做到:

  • - 順序訪問
  • - 儘可能在最內層的迴圈中進行迭代,提高向量利用率

  • - 儘可能的重用資料,例如卷積層中的權重

通常,對於 CPU 上的某些張量操作,原生 TensorFlow 資料格式並不是最有效的資料佈局。對於 TensorFlow 中的 tensor, 所有 OneDNN 中的運算元使用都是高度最佳化的資料佈局。在這種情況下,我們插入一個從 TensorFlow 原生格式到內部格式的資料佈局轉換操作,在 CPU 上執行操作,並將操作輸出轉換回 TensorFlow 原生格式。需要注意的是我們應該避免冗餘的轉化開銷。而這些轉換會帶來效能開銷,因此帶來的挑戰在於如何避免不必要的轉換。所以,我們應該採用佈局傳播方式,佈局傳播就是用於識別出相鄰的互逆 reorder,並消除它們,從而減少了無效的操作。也就是最右邊的這張圖中的結構。

圖6. 佈局傳播

在佈局傳播方面,Intel ® Optimization for TensorFlow*中所做的最佳化為

  • 查詢子圖,這個子圖中所有運算元都有OneDNN支援

  • 在這樣的子圖的邊界上,引入資料佈局轉換

3)在系統級最佳化方面 ,包括負載均衡與記憶體分配兩部分。對於負載均衡,我們知道不正確的設定執行緒模型引數會引發效能問題。因此,可以參閱TensorFLow裡的相關說明文件,正確的為模型設定引數。對於記憶體分配,TensorFlow中的神經網路運算元會分配大量的記憶體。但 TensoeFlow 中預設的 CPU 分配器不能很好地處理這種情況: 頻繁alloc/dealloc 會帶來頻繁的mmap/munmap。在Intel ® Optimization for TensorFlow*中實現了 Pool allocator 來解決這個問題。

2.2.2 Intel ®Optimization for PyTorch*

我們已經將大部分最佳化上傳到 社群版本的 PyTorch 中,同時還保留了一個單獨的英特爾 PyTorch 擴充套件包(Intel ® Extension for PyTorch* (IPEX))作為目前尚未upstream的這些最佳化的一個緩衝區。
圖7. Intel ® Extension for PyTorch*
IPEX 在英特爾硬體上對比社群版本的 pytorch 具有額外的效能提升。大多數最佳化最終將包含在社群 PyTorch 版本中,擴充套件包的目的是在英特爾硬體上為 PyTorch 提供最新的特性和最佳化,包括 AVX512 VNNI) 和 Intel ®AMX。
IPEX可以作為Python程式中的模組進行載入,也可以作為 C++ 程式的 C++ 庫連結。使用者可以透過匯入 intel_extension_for_pytorch 在指令碼中動態啟用這些最佳化。
最佳化擴充套件包 IPEX 中所包含的最佳化有:

  • 運算元最佳化:為提高效能,IPEX最佳化了運算元並實現了多個定製的運算元。(透過ATen序號產生器制,一些ATen運算子會被在Intel ® Extension for PyTorch*的最佳化版本所取代。)還針對幾種流行的拓撲實現了一些定製運算元。如Mask R-CNN中的 ROIAlign and NMS.

  • 圖最佳化:IPEX支援常用的運算元融合,如Conv2D+ReLU, Linear+ReLU等。運算元融合帶來的好處以透明的方式傳遞給使用者。IPEX支援FP32 和 BF16 融合模式,以及INT8融合模式

  • Runtime 最佳化: 為使用者提供了多個 PyTorch 前端 API,以便對執行緒執行時進行更細粒度的控制。它提供

  • - 透過 Python 前端模組 MultiStreamModule 進行多流推理

  • - 從 Python 和 C++ 前端生成非同步任務

  • - 從 Python 和 C++ 前端為 OpenMP 執行緒配置核心繫結

2.3 最佳化工具 INC

INC全稱為Intel ® Neural Compressor,是一個執行在Intel CPU和GPU上的開源Python 庫,它為流行的網路壓縮技術 (如量化、剪枝、知識蒸餾) 提供跨多個深度學習框架的統一介面。
圖8. INC基礎架構圖
可以看到,這個工具支援自動的精度驅動的調優策略,幫助使用者快速找到最佳量化模型。 這些調優策略包括貝葉斯/MSE/TPE…
對於量化部分,模型量化主要是透過降低模型中tensor和weights精度的手段,從而減少計算需求和資料儲存與傳輸需求,來達到加速的目的。主要方法分兩派:一是訓練後量化(Post-training Quantization),二是量化感知訓練(Quantization-Aware Training)。
INC工具支援 

  • 訓練後靜態量化(Post-training Static Quatization)

  • 訓練後動態量化(Post training dynamic Quatization)

  • 量化感知訓練(Quantization-aware training)

對於剪枝部分,深度學習網路模型從卷積層到全連線層存在著大量冗餘的引數,大量神經元啟用值趨近於 0,將這些神經元去除後可以表現出同樣的模型表達能力,這種情況被稱為過引數化,而對應的技術則被稱為模型剪枝。INC 中採用多種剪枝演算法,如非結構化剪枝(Magnitude-based 基於幅度剪枝), 結構化剪枝(Gradient sensitivity梯度敏感剪枝),生成具有預定義稀疏性目標的剪枝模型。

同時 INC 也支援知識蒸餾。模型蒸餾採用的是遷移學習的方法,透過採用預先訓練好的複雜模型(Teacher Model)的輸出作為監督訊號去訓練另外一個簡單的網路(Student Model),最後把 Student Model 用於推理。
以在 TensorFlow 上的使用舉例,使用者模型可以是 saved model、 ckpt、 pb 各種形式,透過 INC 工具執行後,得到一個最佳化後的模型,依然為之前的使用者模型格式,可以在 Tensorflow 上使用,相較於原始模型來說獲得更好的效能效果。
圖9. INC效能表現
這是在 150+ 個業內常用的模型,使用 INC 工作後的評估結果。這些模型涉及各個領域,包括影像分類中常用的ResNet、GoogLeNet、Inception,目標檢測中常用的Mobilenet、Yolo、Faster RCNN,推薦中常用的 Wide&deep、DLRM,自然語言處理中常用的 bert 等。這張圖展現的是 int8 相對於fp32 的效能結果比較。橫軸為相應的精度改變,縱軸為 Int8 與 fp32 相比在實時 latency 的提升。可以看到幾何平均提升達到 2.3 倍。
三、效能最佳化方法及案例分享
3.1 效能最佳化方法
在推理的效能最佳化方面, 工作可歸成四類:運算元最佳化、圖最佳化、模型壓縮和部署最佳化。
運算元最佳化:  運算元最佳化中微架構最佳化的主要焦點是如何充分利用好微架構的內建加速器的能力去最大化運算元的效能。OneDNN底層庫就可以幫大家很好的做這部分的最佳化。
圖最佳化: 主要透過子圖變換和運算元融合等方式來達到減少計算量或者其他系統開銷(如訪存開銷),從而達到效能最佳化的目的。圖最佳化主要是希望在不影響模型的數值特性的基礎上,透過圖變換達到簡化計算、資源開銷,提升效能,所以是效能最佳化時的首選方法之一。英特爾對於深度學習框架tensroflow, pytorch的最佳化包含這些圖最佳化。
模型壓縮: 如果還需要額外的效能增益,這時候需要考慮模型壓縮方案。模型壓縮(Compression)主要手段有:模型量化、剪枝和模型蒸餾。工程師們也可以透過剛剛介紹的INC壓縮工具來便捷的使用到這些壓縮方案。
部署最佳化: 主要透過調整模型在部署時的資源分配和排程的引數來進一步最佳化效能。
3.2 案例分享:Bfloat16 最佳化在第三代英特爾至強可擴充套件處理器上提升阿里雲 BERT 模型效能
BERT 模型是一個自然語言處理中的一個常用模型。阿里巴巴阿里雲團隊與 Intel 工程師密切合作進行 BERT 推理效能最佳化。接下去介紹我們是怎樣一步步開展這些最佳化的。首先,我們在原始資料型別,即fp32的情況下,我們首先使用“模型轉換”將多層多操作的複雜 BERT 模型替換為單個 BERT 操作。為了在 TensorFlow上實現高效的 BERT op,我們需要建立一個最佳化的Kernel,從而產生一個新的自定義 BERT 運算元。這是一個具有 運算元 融合和最佳化的實現。
在 TensorFlow 中,“前端”負責圖描述,“後端”負責運算元的執行。因此,我們可以將模型從原始 BERT 模型轉換為前端帶有 BERT op 的新模型,並將新的 BERT 核心實現註冊到後端。因此,我們不需要重新安裝 TensorFlow 框架。我們只需要載入實現 BERT 程式碼的動態庫即可,並透過 oneAPI 深度神經網路庫 (oneDNN)等高效能工具,來提升效能。
圖10. BERT 模型最佳化方案
對於最佳化實現,我們分析BERT圖進行層融合和張量融合。這張圖顯示了 12 層 BERT 中的一層細節。
在這個案例中,又可以進行橫向融合和縱向融合。關於橫向融合,我們可以看到三個張量,即查詢 query、鍵 key 和值 value,都需要進行 MatMul 和 BiasAdd 操作。我們可以把這些操作融合為一個操作,即 QKV MatMul 和 BiasAdd。關於縱向融合,可以參照下圖。
圖11. 新BERT模型實現
接下去,我們分析最佳化的 FP32 BERT 模型時,我們注意到推理過程中超過 80% 的執行時間花費在 MatMul 操作中。如何最佳化 MatMul 運算以減少延遲已成為最緊迫的挑戰之一。眾所周知,減少記憶體訪問、最佳化快取、提高並行度可以最佳化程式效能。隨著第 3 代英特爾至強可擴充套件處理器的引入,使用最開始介紹的英特爾 DL Boost 的 bfloat16 指令,與 FP32 的點積相比,在理論上能將 BF16 的點積加速 2 倍。
英特爾 ® 深度學習加速技術包括以下 BFloat16 指令:

為了減少記憶體訪問,我們將 FP32 權重轉換為 BF16 權重,像下圖中右邊的圖結構所示。我們將 FP32 權重轉換為 BF16 權重並將 BF16 權重快取在 BF16 MatMul op 中以供重用,並在每次執行時並行的將 FP32 輸入轉換為 BF16 輸入。

圖12. BFloat16 最佳化方案

在這樣的轉化下,我們可以使用 bfloat16 的點積計算 MatMul op,可以看到輸入為 BF16 型別, 輸出為 fp32 型別。 這些實現是利用了 oneDNN的 支援。 因此,我們只需要建立一個新的 BF16 MatMul op 來替換最佳化的 FP32 解決方案(Baseline)MatMul op,然後我們就可以實現BF16與 FP32 最佳化相比帶來的效能提升。

對於 BF16 最佳化方案,透過簡單的運算替換來提高效能,可以保持儘可能高的精度。對於 BiasAdd 操作,我們仍然保持 FP32 操作,以減少精度損失。

最後是一個最佳化後方案的效能和進度評估結果,為了比較最佳化後的 FP32 Bert 和最佳化後的 BF16 Bert 的效能差異,我們將batch size 設為1,token size 設為128,這也符合實際的線上業務。輸入是 MRPC 資料集。以延時為 21.70 毫秒的 FP32 解決方案為基準,可以看到最佳化的 BF16 解決方案與基線相比,延遲為 11.83 毫秒,端到端的效能提升達到了 1.83 倍,並且沒有 Accuracy 的損失。


敲重點啦

本次直播影片回放已上線至龍蜥社群官網(首頁-社群-影片),直播 PPT 獲取方式:關注龍蜥社群公眾號,後臺回覆 【龍蜥課件】 【龍蜥影片回放】 即可。

相關連結地址 也可移步龍蜥社群公眾號2022年3月11日相同推送檢視

—— 完 ——

加入龍蜥社群

加入微信群:新增社群助理-龍蜥社群小龍(微信:openanolis_assis),備註【龍蜥】與你同在;加入釘釘群:掃描下方釘釘群二維碼。歡迎開發者/使用者加入龍蜥社群(OpenAnolis)交流,共同推進龍蜥社群的發展,一起打造一個活躍的、健康的開源作業系統生態!

關於龍蜥社群

龍蜥社群OpenAnolis)是由 企事業單位、高等院校、科研單位、非營利性組織、個人等在自願、平等、開源、協作的基礎上組成的非盈利性開源社群。龍蜥社群成立於 2020 年 9 月,旨在構建一個開源、中立、開放的Linux 上游發行版社群及創新平臺。

龍蜥社群成立的短期目標是開發龍蜥作業系統(Anolis OS)作為 CentOS 停服後的應對方案,構建一個相容國際 Linux 主流廠商的社群發行版。中長期目標是探索打造一個面向未來的作業系統,建立統一的開源作業系統生態,孵化創新開源專案,繁榮開源生態。

目前, 龍蜥OS 8.4 已釋出,支援 X86_64 、Arm64、LoongArch 架構,完善適配 Intel、飛騰、海光、兆芯、鯤鵬、龍芯等晶片,並提供全棧國密支援。

歡迎加入我們,一起打造面向未來的開源作業系統!




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004278/viewspace-2871018/,如需轉載,請註明出處,否則將追究法律責任。

相關文章