基于TensorRT的BERT实时自然语言理解(下)
基于TensorRT的BERT實時自然語言理解(下)
BERT Inference with TensorRT
請參閱Python腳本bert_inference.py還有詳細的Jupyter notebook BERT_TRT.ipynb在sample文件夾中進行推理過程的逐步描述和演練。在本節中,讓我們回顧幾個關鍵參數和概念,以便使用TensorRT進行推理。
BERT(更具體地說是編碼器層)使用以下參數來控制其操作:
-
Batch size
-
Sequence Length
-
Number of attention heads
這些參數的值取決于所選的BERT模型,用于設置TensorRT計劃文件(執行引擎)的配置參數。
對于每個編碼器,還要指定隱藏層的數量和注意頭的大小。您也可以從Tensorflow檢查點文件中讀取上述所有參數。
由于我們所使用的BERT模型已經針對SQuAD數據集上的問答下游任務進行了微調,網絡的輸出(即輸出完全連接層)將是一段文本,答案出現在文章中(在示例中稱為h_output)。一旦我們生成了TensorRT引擎,我們就可以對其進行序列化,然后在TensorRT運行時中使用它。
在推理過程中,我們異步地執行從CPU到GPU的內存復制,反之亦然,從而分別將張量導入和移出GPU內存。異步內存復制操作通過與設備和主機之間的內存復制操作重疊計算來隱藏內存傳輸的延遲。異步內存復制和內核執行如圖3所示。
Figure 3: TensorRT Runtime process
The inputs to the BERT model, which are shown in Figure 3, include:
-
input_ids: tensor with token ids of paragraph concatenated along with question that is used as input for inference
-
segment_ids: distinguishes between passage and question
-
input_mask: indicates which elements in the sequence are tokens, and which ones are padding elements
輸出(start_logits)和end_logits結束邏輯表示答案的范圍,網絡根據問題在文章中預測答案的范圍。
在Jupyter筆記本中,我們使用了作為TensorRT插件實現的層的加速和高效實現。請參閱TensorRT文檔以了解有關TensorRT插件以及如何在TensorRT中導入自定義層的更多信息。
Optimizing BERT for Inference
讓我們瀏覽一下在TensorRT優化的BERT中實現的關鍵優化。 BERT架構基于Transformer,由12個用于BERT基的Transformer單元和24個用于BERT大型單元的Transformer單元組成。在被Transformer處理之前,輸入標記通過一個嵌入層傳遞,該層查找它們的向量表示并對它們在句子中的位置進行編碼。每個Transformer單元由兩個連續的剩余塊組成,每個剩余塊隨后進行層標準化。第一殘差塊代替第一完全連通層并通過多頭自注意機制激活,第二剩余塊使用高斯誤差線性單元(GELU6)激活。
圖4說明了Transformer單元的結構。
為了用TensorRT優化BERT,我們重點研究了Transformer單元的優化。由于在BERT中堆疊了幾個Transformer單元,因此我們能夠通過這組優化實現顯著的性能提升。
為了在TensorRT中使用這些優化,我們使用定制插件來加速BERT模型中Transformer編碼器元素中的關鍵操作。插件將多個操作融合到單個CUDA內核中的子圖中。每個子圖由幾個基本計算組成,每個計算都需要對GPU的全局內存(即最慢的設備內存)進行讀寫。通過將基本操作融合到單個CUDA內核中,我們允許計算在更大的子圖上進行,同時訪問全局內存的次數最少。讓我們更詳細地看看這些插件。
Figure 4: Optimizations through TensorRT for
BERT encoder cell of Transformer
The Gelu Activation performs the
following elementwise computation where a, b and c are some scalar
constants:
gelu(x) = a * x * (1 + tanh( b * (x + c * x^3) ))
A naive implementation using elementary layers
in TensorRT would require the following operations:
Result = x^3
Result = c * Result
Result = x + Result
Result = b * Result
Result = tanh(Result)
Result = x * Result
Result = a * Result
對于k層,樸素的實現將需要。k-1不必要的全局內存往返,我們將其合并到單個CUDA內核中的元素計算中。參考geluPlugin.cu目錄中獲取更多詳細信息。
跳過層和層規范化(LN)層在每個轉換器層出現兩次,并在單個內核中融合。有關此融合操作的實現,請參見中的skipLayerNormPlugin.cu在plugins目錄中。
Transformer中的自我注意機制(圖5)基于使用完全連接(FC)層的輸入嵌入計算查詢(Q)、鍵(K)和值(V)的表示。所有這些FC層的輸入和輸出維都是B x S x(NH),其中B是批大小,S是序列長度,N是注意頭數,H是隱藏層大小。然后將每個FC層的輸出轉置以形成大小為B x N x S x H的結果矩陣。將3個FC層合并到單個較大的層中可得到B x S x(3N*H)的輸出維度。
在融合的FC層之后,有三個轉置操作可以被融合到單個更大的轉置中,從而產生3xb×N×S×H的輸出維。通過融合FC層,然后在較大張量上執行單個轉置,Q、K和V表示被連續地放置在存儲器中,以便進行以下操作他們。這將導致更快的內存訪問,提高模型的吞吐量。
我們還融合了元素級縮放和softmax層(圖5a和5b的右側)。 參考qkvToContextPlugin.cu在自我注意實現的plugins目錄中。
Figure 5a: Self-Attention Layer before
Optimization
Figure 5b: Self-attention Layer after
Optimization
Benchmarking BERT Inference Performance
BERT可以應用于在線和離線用例。在線NLU應用程序,如會話式人工智能,在推理過程中會有較緊的延遲預算。為了響應單個用戶的查詢,需要按順序執行多個模型。當作為服務使用時,客戶體驗的總時間包括計算時間以及輸入和輸出網絡延遲。時間越長,性能就越差,客戶體驗也就越差。 雖然單個模型可用的確切延遲可能因應用程序而異,但多個實時應用程序需要語言模型在10毫秒內執行。使用Tesla T4 GPU,使用TensorRT優化的BERT可以在2.2毫秒內對批處理大小=1、序列長度=128的QA任務執行推斷。使用TensorRT優化的示例,對于BERT base,您可以執行高達8的批處理大小,對于在10毫秒延遲預算內具有較少Transformer層的模型,可以執行更高的批處理大小。對于批處理大小=1,在僅CPU平臺上用高度優化的代碼執行相同的任務需要40毫秒,而更高的批處理大小不會運行到完成并出現錯誤退出。
在這里插入圖片描述
Figure 6: Compute latency in milliseconds for
executing BERT-base on an NVIDIA T4 GPU versus a CPU-only server
該基準測試測量在將張量作為輸入傳遞和將邏輯集作為輸出之間執行QA任務時僅計算的延遲時間。您可以在中找到用于對示例進行基準測試的代碼sampleBERT.cpp.
Conclusion
NVIDIA是開放源碼的幾個優化,使它能夠在2.2ms內使用TensorRT在T4 gpu上執行BERT推斷。優化的代碼可以在TensorRT開源repo中作為開源示例提供。要在GCP上運行這個示例,可以從google cloud ai Hub訪問它。repo展示了如何優化Transformer層,它是BERT和其他幾種語言模型的核心構建塊。我們希望您能夠輕松地定制這些構建塊,以適合您的定制模型和應用程序。本文概述了如何使用TensorRT示例、關鍵優化和性能結果。我們進一步描述了如何使用BERT示例作為簡單應用程序和Jupyter筆記本的一部分的工作流程,在這里您可以傳遞一個段落并詢問與之相關的問題。
新的優化和可實現的性能使得首次將BERT用于延遲預算較緊的應用程序(如會話式AI)成為現實。在接下來的幾個月里,我們希望分享更多的例子,展示如何將BERT用作其他工作流的一部分。
我們一直在尋找新的想法來分享新的例子和應用程序。您使用BERT進行哪些NLP應用程序?您將來希望從我們這里看到哪些示例?
If you have questions regarding the TensorRT sample repo, check the NVIDIA TensorRT Developer Forum to see if
other members of the TensorRT community have a resolution first. NVIDIA Registered Developer Program can also file bugs at https://developer.nvidia.com/nvidia-developer-program.
·
CPU-only specifications: Gold 6240@2.60GHz 3.9GHz Turbo (Cascade Lake) HT Off, Single node, Single Socket,
Number of CPU Threads = 18, Data=Real, Batch Size=1; Sequence Length=128;
nireq=1; Precision=FP32; Data=Real; OpenVINO 2019 R2
GPU-server specification: Gold 6140@2GHz
3.7GHz Turbo (Skylake) HT On, Single node, Dual Socket, Number of CPU Threads =72, Tesla T4 16GB, Driver Version 418.67 (r418_00), BERT-base, Batch Size=1;
Number of heads = 12, Size per head = 64; 12 layers; Sequence Length=128;
Precision=FP16; XLA=Yes; Data=Real; TensorRT 5.1
References:
-
[Devlin et al 2018] BERT: Pre-training of Deep Bidirectional Transformers for Language
Understanding. Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina
Toutanova -
[Y Liu ?2019] RoBERTa: A Robustly Optimized BERT Pretraining Approach
SQuAD leaderboard
-
[Vaswani et al 2017] Attention Is All You Need Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin
-
[Jinhyuk Lee et al 2019] BioBERT: a pre-trained biomedical language representation model for biomedical text mining Jinhyuk Lee, Wonjin Yoon, Sungdong Kim2,Donghyeon Kim1, Sunkyu Kim1, Chan Ho So3 and Jaewoo Kang
-
[Dan et al 2016] Gaussian Error Linear Units (GELUs) Dan Hendrycks,Kevin Gimpel
總結
以上是生活随笔為你收集整理的基于TensorRT的BERT实时自然语言理解(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于TensorRT的BERT实时自然语
- 下一篇: TensorRT 7.2.1 开发概要(