NVIDIA GPUs上深度學習推薦模型的優化
Optimizing the Deep Learning Recommendation Model on NVIDIA GPUs
推薦系統幫助人在成倍增長的選項中找到想要的東西。是在許多在線平台上推動用戶參與的關鍵組件。
隨着工業數據集規模的迅速增長,利用大量訓練數據的深度學習推薦模型(deep learning,DL)已經開始顯示出其相對於傳統方法的優勢。現有的基於DL的推薦系統模型包括廣度和深度模型、深度學習推薦模型(DLRM)、神經協同濾波(NCF)、變分自編碼(VAE)和BERT4Rec等。
大型推薦系統解決方案在性能上面臨着多重挑戰:龐大的數據集、復雜的數據預處理和特征工程管道,以及大量的重復實驗。為了滿足大規模DL推薦系統訓練和推理的計算需求,GPU推薦解決方案旨在提供快速的特征工程和高訓練吞吐量(支持快速實驗和生產再訓練),以及低延遲、高吞吐量的推理。
在這篇文章中,討論了DLRM的參考實現,是NVIDIA GPU加速DL模型組合的一部分。涵蓋了許多不同領域的網絡體系結構和應用,包括圖像、文本和語音分析以及推薦系統。通過DLRM,系統地解決了上述挑戰。
對於海量數據集的數據預處理任務,引入了新的Spark-on-GPU工具。通過NVIDIA Tensor Core GPU上的自動混合精度訓練、優化的數據加載程序和定制的嵌入式CUDA內核,在單個Tesla V100 GPU上,只需44分鍾就可以在Criteo Terabyte數據集上訓練DLRM模型,而在96-CPU線程上則需要36.5小時。
還演示了如何使用NVIDIA Triton推理服務器將經過訓練的DLRM模型部署到生產環境中。
DLRM overview
DLRM是一個基於DL的推薦模型,由Facebook research引入。與其基於DL的方法一樣,DLRM被設計為同時使用推薦系統訓練數據中通常存在的分類輸入和數值輸入。圖1顯示了模型架構。為了處理類別數據,嵌入層將每個類別映射到一個密集的表示,然后再將其輸入多層感知器(MLP)。數值特征可以直接輸入MLP。
在下一個層次上,通過在所有嵌入向量對和處理的稠密特征之間取點積,顯式地計算不同特征的二階交互作用。這些成對交互被輸入到頂級MLP中,以計算用戶和項目對之間交互的可能性。
Figure 1. DLRM architecture.
與其基於DL的推薦方法相比,DLRM在兩個方面有所不同。首先,顯式地計算特征交互,同時將交互順序限制為成對交互。
其次,DLRM將每個嵌入的特征向量(對應於分類特征)視為一個單元,而其方法(如Deep和Cross)將特征向量中的每個元素視為一個新單元,該單元應產生不同的交叉項。這些設計選擇有助於降低計算/內存成本,同時保持具有競爭力的准確性。
Criteo dataset
Criteo-Terabyte-click-logs公共數據集是推薦任務中最大的公共數據集之一,提供了對真實企業數據規模的難得一瞥。包含約1.3 TB的未壓縮點擊日志,包含超過40億個24天的樣本,可用於訓練預測廣告點擊率的推薦系統模型。
這是公共DL數據集中的一個大型數據集。然而,真實的數據集可能要大一兩個數量級。企業盡量利用盡可能多的歷史數據,因為這通常轉化為更好的准確性。
在本文中,使用Criteo Terabyte數據集來演示GPU優化的DLRM訓練管道的效率。此數據集中的每條記錄都包含40個值:一個表示單擊(值1)或不單擊(值0)的標簽、13個數值特征值和26個分類特征值。特性是匿名的,分類值是散列的,以確保隱私。
End-to-end training pipeline
1. 提供了一個關於Criteo Terabyte數據的端到端訓練管道,幫助從幾個簡單的步驟開始。
1. copy存儲庫。Clone the repository.
git clone https://github.com/NVIDIA/DeepLearningExamples
cd DeepLearningExamples/PyTorch/Recommendation/DLRM
2. 構建DLRM Docker容器 Build a DLRM Docker container
docker build . -t nvidia_dlrm_pyt
在NVIDIA NGC容器中啟動交互式會話以運行預處理/訓練和推理。DLRM PyTorch容器可以通過以下方式啟動:
mkdir -p data
docker run --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_pyt bash
4. 在Docker交互會話中,下載並預處理Criteo TB數據集。
在下載數據之前,必須簽訂並同意Criteo Terabyte數據集的條款和條件。該數據集包含24個壓縮文件,需要大約1 TB的磁盤存儲空間來存儲數據,另外2 TB的磁盤存儲空間來立即得到結果。
如果不想在24個文件的完整集合上進行實驗,可以下載一個子集文件並修改數據預處理腳本以僅處理這些文件。
cd preproc && ./prepare_dataset.sh && cd -
5. Start training.
python -m dlrm.scripts.main --mode train --dataset /data --save_checkpoint_path model.pt
接下來,將討論這個訓練管道的幾個細節。
Data preprocessing and transformation with Spark
最初的Facebook DLRM代碼庫附帶了一個數據預處理實用程序來預處理數據。
對於數值特征,數據預處理步驟包括用0填充缺失值和歸一化(將值移動到>=1並取自然對數)。
對於分類特征,預處理將哈希值轉換為從0開始的連續整數范圍。
這個基於NumPy的數據實用程序運行在一個CPU線程上,需要大約5.5天來轉換整個Criteo Terabyte數據集。
使用Spark改進了數據預處理過程,以充分利用所有可用的CPU線程。在DLRM Docker映像中,使用了Spark 2.4.5,啟動了一個獨立的Spark集群。這將顯著提高數據預處理速度,並隨着可用CPU內核數的增加而擴展。Spark以Parquet格式輸出轉換后的數據。最后,將Spark 數據文件轉換成一種二進制格式,專門為Criteo數據集設計。
在一個具有96核和768GB RAM的AWS r5d.24xl實例上,整個過程需要9.45小時(不帶頻率上限)和2.87小時(帶頻率上限),以便將出現次數少於15次的所有罕見類別映射到一個特殊類別)。
Spark可以進一步提高。為DLRM引入了一個Spark GPU插件。圖2顯示了GPU上Spark的數據預處理時間改進。使用8v100 32-gbgpu,與等效的Spark CPU管道相比,可以將處理時間進一步加快43倍。Spark GPU插件目前正處於早期訪問階段,供選定的開發人員使用。邀請注冊對Spark GPU插件的興趣。
Figure 2: Spark performance improvement on GPU vs CPU. CPU model: AWS r5d.24xl, 96 cores, 768 GB RAM. Bars represent speedup factor for GPU vs. CPU. The higher, the better.
預處理腳本是為Criteo Terabyte數據集設計的,但是應該可以與任何其具有相同格式的數據集一起使用。數據應該分成文本文件。這些文本文件的每一行都應該包含一個訓練示例。示例應包含多個字段,這些字段由制表符分隔:
第一個字段是標簽。正數用1,負數用0。
接下來的N個標記應該包含由制表符分隔的數字特征。
下一個M標記應該包含由制表符分隔的散列分類特性。
必須修改數據參數,例如每個分類特征的唯一值的數目和predoc/spark_data中的數字特征的preproc/spark_data_utils.py,以及預印/運行中的spark配置preproc/run_spark.sh.
Data loading
采用二進制數據格式,本質上是對加載速度特別快的NumPy數組的序列化。這與重疊數據加載和host2設備傳輸以及神經網絡計算相結合,使能夠實現高GPU利用率。
Embedding tables and custom embedding kernel
基於DL的推薦模型通常太大,無法裝入單個設備內存。這主要是由於嵌入表的絕對大小,與類別特征的基數和潛在空間的維數(嵌入表中的行數和列數)成正比。
采用了一種常見的做法,將所有罕見的分類值映射到一個特殊的“缺失類別”值(這里,在數據集中出現次數少於15次的任何類別都被視為缺失類別)。這減少了嵌入表的大小,並避免了嵌入那些在隨機初始化的訓練過程中無法充分更新的條目。
與其計算密集型層不同,嵌入層受內存帶寬限制。與當前最先進的商用CPU相比,GPU具有非常高的帶寬內存。為了有效地使用可用的內存帶寬,將所有分類嵌入表合並到一個表中,並使用自定義內核執行嵌入查找。內核使用矢量化的加載存儲指令以獲得最佳性能。
Training with automatic mixed precision
混合精度是指在計算過程中使用多個數值精度,如FP32和FP16。
從Volta架構開始,NVIDIA gpu配備了張量核、執行矩陣乘法的專用計算單元、線性(也稱為完全連接)和卷積層的構建塊。NVIDIA NGC PyTorch容器中提供的自動混合精度(AMP)功能使混合精度訓練只需對代碼庫進行最小的更改。在引擎啟動下,AMP是由NVIDIA APEX庫提供的,通過只更改腳本的三行來實現混合精度訓練。
在對NVIDIA DL模型庫中的各種模型和體系結構的實驗中,AMP通常提供1.3倍到3倍或更多的加速。對於DLRM,AMP提供了比FP32訓練快2.37倍的速度。使用V100 32GB的GPU,DLRM可以在44分鍾內在Criteo Terabyte數據集上訓練一個epoch,收斂到AUC值0.8036。
End-to-end inference pipeline
推薦系統推理包括確定查詢用戶最有可能與之交互的項的有序列表。
對於有數百萬到數億個項目可供選擇的大型商業數據庫(如廣告或應用程序),通常執行項目檢索過程以將項目數量減少到更易於管理的數量,例如幾百到幾千個。這些方法包括計算效率高的算法,例如基於用戶偏好和業務規則的近似鄰域搜索或過濾。在此基礎上,調用一個DL推薦模型來重新排列條目。得分最高的將呈現給用戶。這個過程如圖3所示。
Figure 3: Recommender systems inference process.
如所見,對於每個查詢用戶,要評分的用戶項對的數量可以大到幾千個。這給推薦系統推理服務器帶來了沉重的負擔。服務器必須處理高吞吐量以同時服務多個用戶,同時以低延遲運行以滿足在線商務引擎的嚴格延遲閾值。
NVIDIA Triton推理服務器提供了一個為NVIDIA gpu優化的雲推理解決方案。服務器使用HTTP或GRPC端點提供推理服務,允許遠程客戶端請求對服務器管理的任何模型進行推理。Triton服務器自動管理和使用所有可用的GPU。
下一節將介紹如何准備DLRM模型,以便與Triton服務器進行推理,並了解Triton服務器的性能。
Prepare the model for inference
Triton服務器可以為TorchScript和ONNX模型以及其模型提供服務。提供了一個導出工具來准備經過訓練的DLRM模型,以便進行生產推斷。
使用TorchScript
可以使用以下任一方法將預處理的PyTorch DLRM模型導出到TorchScript模型torch.jit.script腳本或者torch.jit.trace使用以下命令:
python triton/deployer.py --ts-script --triton-max-batch-size 65536 --model_checkpoint dlrm.pt --save-dir /repository [other optional parameters]
這將從名為dlrm.pt公司,使用torch.jit.script腳本最大可維護批量為65536。
使用ONNX
類似地,可以使用以下命令創建ONNX生產就緒模型:
python triton/deployer.py --onnx --triton-max-batch-size 65536 --model_checkpoint dlrm.pt --save-dir /repository [other optional parameters]
導出工具的結果是一個打包的目錄/存儲庫,Triton服務器可以很容易地利用。
設置Triton推理服務器
在模型准備就緒的情況下,Triton服務器可以通過以下步驟進行設置。
使用以下命令下載Triton推理Docker圖像,其中<tag>是服務器版本,例如20.02-py3:
docker pull nvcr.io/nvidia/tensorrtserver:<tag>
啟動Triton服務器,指向在上一步中創建的導出模型目錄:
docker run --network=host -v /repository:/models nvcr.io/nvidia/tensorrtserver:<tag> trtserver --model-store=/models
Use the Triton Server perf_client tool to measure inference performance
Triton服務器配有一個方便的性能客戶端工具perf_客戶端。該工具使用多個並行線程,使用合成數據或實際數據對推理服務器進行壓力測試。可以使用以下命令調用:
/workspace/install/bin/perf_client --max-threads 10 -m dlrm-onnx-16 -x 1 -p 5000 -v -i gRPC -u localhost:8001 -b 4096 -l 5000 --concurrency-range 1 --input-data /location/for/perfdata -f result.csv
使用perf客戶機,收集了延遲和吞吐量數據,以填充本文后面顯示的數字。 Triton服務器批處理策略
默認情況下,導出的模型與Triton服務器靜態批處理策略一起部署:每個請求都會立即完成。另一方面,動態批處理是推理服務器的一個特性,允許服務器組合推理請求,以便動態創建批處理。這將導致批量推理請求的吞吐量增加。
同時對一批輸入進行推理,這對gpu尤其重要,因為可以大大提高推理吞吐量。在許多用例中,單個推理請求沒有批處理,也沒有從批處理的吞吐量效益中獲益。
對於具有嚴格延遲閾值的在線應用程序,Triton服務器是可配置的,因此具有動態批處理的隊列時間被限制在上限,同時形成盡可能大的批處理以最大化吞吐量。在模型目錄中,有一個名為config.pbtxt可以配置一個額外的批處理選項,如下所示:
ddynamic_batching {
preferred_batch_size: [ 65536 ]
max_queue_delay_microseconds: 7000
}
靜態批處理吞吐量 ‘
圖4顯示了Triton服務器在不同批量大小下的吞吐量。對於推薦系統,大批量是最感興趣的。對於每個查詢用戶,在一個項目重新排序的請求中會發送數千個項目。與80線程CPU推斷相比,Tesla V100 32-GB GPU的吞吐量提高了20倍。可以看到,GPU的吞吐量在大約8K的批處理大小時開始飽和。
Figure 4. Triton Server TorchScript inference throughput on GPU vs. CPU. GPU: Tesla V100 32GB. CPU: 2x Intel(R) Xeon(R) E5-2698 v4 @ 2.20GHz (80 threads).
圖5顯示了與CPU相比,GPU上的Triton TorchScript推理延遲。在8192的批處理大小下,V100 32-GB GPU比80線程CPU推斷減少了19倍的延遲。
Figure 5. Triton TorchScript inference latency on GPU vs. CPU. GPU: Tesla V100 32 GB. CPU: 2x Intel(R) Xeon(R) E5-2698 v4 @ 2.20GHz (80 threads).
動態批處理吞吐量
與靜態批處理相比,使用動態批處理可以進一步提高吞吐量。在這個實驗中,將每個用戶的請求批量大小設置為1024,Triton最大和首選批量大小設置為65536。圖5顯示了不同請求並發級別的延遲和吞吐量。延遲分為客戶端發送/接收時間、服務器隊列和計算時間、網絡、服務器發送/接收時間。
並發級別是perf_client的一個參數,允許控制延遲吞吐量權衡。默認情況下,perf_client在請求並發性為1時使用模型上可能的最低負載來測量模型的延遲和吞吐量。為此,perf_client向服務器發送一個推斷請求並等待響應。當接收到該響應時,perf_client立即發送另一個請求,然后重復此過程。
在N的更高並發級別上,perf_client立即一個接一個地觸發請求,而不等待前一個請求得到滿足,同時在任何時候最多保持N個未完成的請求。
Figure 6. Latency vs. throughput at varying number of concurrent client requests on Tesla V100 32GB GPU. Model: DLRM TorchScript FP16. Maximum Triton batch size: 65536.
圖6顯示,如果延遲上限為10毫秒,則可以達到每秒1318710個樣本的吞吐量。這意味着在一個V100 GPU上每秒可以為1288個用戶提供服務,每個用戶在10毫秒的延遲限制內,假設希望為每個用戶評分1024項,並且用戶請求在任何10毫秒窗口內以最大12個請求的統一速率出現。
結論
在這篇文章中,經歷了一個完整的DLRM管道,從數據准備到培訓再到生產推理。GPU優化的DLRM可從NVIDIA deep learning model zoo的/PyTorch/Recommendation/DLRM下獲得。提供現成的Docker圖像用於訓練和推理、數據下載和預處理工具,以及Jupyter演示筆記本,讓快速啟動和運行。通過導出工具,經過訓練的模型可以在一個簡單的步驟中為生產推理做好准備。還邀請注冊興趣,以便盡早訪問Spark GPU組件。
DLRM是NVIDIA Merlin的一部分,NVIDIA Merlin是一個用於構建基於DL的高性能推薦系統的框架。要了解有關Merlin和更大的生態系統的更多信息,請參閱最近的文章,宣布NVIDIA Merlin:一個用於深度推薦系統的應用程序框架。
誠邀試用最新開發的推薦系統應用工具並從中受益。問題和功能請求有助於指導未來的開發。很高興看到可以用自己的數據處理這個模型。