丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗(yàn),強(qiáng)烈建議使用更快更安全的瀏覽器
此為臨時(shí)鏈接,僅用于文章預(yù)覽,將在時(shí)失效
人工智能開發(fā)者 正文
發(fā)私信給汪思穎
發(fā)送

0

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

本文作者: 汪思穎 2018-03-27 09:50
導(dǎo)語:帶來至少 13 倍的 batch 矩陣相乘(matmul)加速

雷鋒網(wǎng) AI 研習(xí)社按,日前,阿里機(jī)器翻譯團(tuán)隊(duì)和 PAI 團(tuán)隊(duì)發(fā)表博文,闡述將 TVM 引入 TensorFlow,可以帶來至少 13 倍的 batch 矩陣相乘(matmul)加速。雷鋒網(wǎng) AI 研習(xí)社將原文編譯整理如下:

背景

神經(jīng)機(jī)器翻譯(NMT)是一種端到端的自動翻譯方法,可能克服傳統(tǒng)的基于短語的翻譯系統(tǒng)的缺點(diǎn)。最近,阿里巴巴集團(tuán)正致力于在全球電子商務(wù)中部署 NMT 服務(wù)。

目前,我們將 Transformer(https://arxiv.org/pdf/1706.03762.pdf) 作為 NMT 系統(tǒng)的核心組成。相較于傳統(tǒng)基于 RNN/LSTM 的方法,它更適合于高效的離線訓(xùn)練,有著相同或更高的精度。

Transformer 在時(shí)間步長中打破了相關(guān)性,對離線訓(xùn)練更友好,但在在線推理上,它并沒有那么高效。我們在生產(chǎn)環(huán)境中發(fā)現(xiàn)初版 Transformer 的推理速度大約比 LSTM 版本慢 1.5 倍到 2 倍。為了提高推理性能,我們已經(jīng)進(jìn)行了一些優(yōu)化,包括圖級別的 op 融合、循環(huán)不變節(jié)點(diǎn)外提(loop invariant node motion)。我們觀察到一個(gè)特殊問題:batch 矩陣相乘是 Transformer 中的一個(gè)關(guān)鍵問題,目前它在 cuBLAS 中的實(shí)現(xiàn)并未得到很好的優(yōu)化。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

圖1:Transformer 模型架構(gòu)

下圖表明,通過 TVM 生成的內(nèi)核可以帶來至少 13 倍的 batch 矩陣相乘加速,伴隨算子融合,速度將更快。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

batch 矩陣相乘

為什么選擇利用 batch 矩陣相乘

在 Transformer 中,batch 矩陣相乘被廣泛應(yīng)用于 multi-head attention 的計(jì)算。利用 batch 矩陣相乘,可以并行運(yùn)行 attention 層中的 multiple heads,這有助于提高硬件的計(jì)算效率。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

圖2:左圖為 Scaled Dot-Product Attention,右圖為并行運(yùn)行若干 attention 層的 Multi-Head Attention

我們在推理階段對 Transformer 模型進(jìn)行了全面分析,結(jié)果表明,batch 矩陣相乘計(jì)算的開銷達(dá)到 GPU 內(nèi)核執(zhí)行時(shí)間的 30%。當(dāng)使用 nvprof 對 cuBLAS batch 矩陣相乘內(nèi)核做一些第一原理(first-principle)分析,很明顯,這種方法的表現(xiàn)并不好,同時(shí)我們還發(fā)現(xiàn)幾個(gè)有趣的現(xiàn)象。

什么是 batch 矩陣相乘

通常,batch 矩陣相乘計(jì)算會在一批矩陣上執(zhí)行矩陣-矩陣乘法。batch 被認(rèn)為是「統(tǒng)一的」,即所有實(shí)例都具有相同的維度(M,N,K)、leading 維度 (lda,ldb,ldc) 和它們各自的 A、B、C 矩陣的轉(zhuǎn)置。

batch 矩陣相乘計(jì)算具體可以描述如下:

void BatchedGemm(input A, input B, output C, M, N, K, batch_dimension) {
 for (int i = 0; i < batch_dimension; ++i)  {
   DoGemm(A[i],B[i],C[i],M,K,N)
 }
}

batch 矩陣相乘形狀

在語言翻譯任務(wù)中,batch 矩陣相乘的形狀比在其他工作負(fù)載下的常規(guī)矩陣相乘計(jì)算要小得多。Transformer 的形狀與輸入語句的長度和解碼器步長有關(guān)。一般來說小于 30。

至于 batch 維度,當(dāng)給定推理 batch 大小時(shí),它是固定數(shù)字。例如,如果 batch size 是 16,beam size 是 4,batch 維度是 16 * 4 * #head (在 multi-headattention 中 head 的數(shù)目,通常為 8)。矩陣 M、K、N 的范圍在 [1, max decode length] 或 [1, max encode length] 內(nèi)。

batch 矩陣相乘的性能問題

首先,我們在理論上對 batch 矩陣相乘內(nèi)核進(jìn)行了 FLOP 分析。結(jié)果非常有趣:所有 batch 矩陣相乘的計(jì)算強(qiáng)度都是受限的(TFLOP 數(shù)少于 1)。

然后,我們通過 nvprof 描述了多形狀 batch 矩陣相乘的 cuBLAS 性能。下面的表格中是使用 NVIDIA M40 GPU(CUDA 8.0)得到的一些指標(biāo)。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

即使形狀不同(在 M、N、K 間變化),所有 maxwell_sgemmBatched_128x128_raggedMn_tn 調(diào)用執(zhí)行的都是相同的 FLOP 數(shù),這比理論值大得多。從中可以推斷,所有這些不同的形狀最終都會被填充成確定的形狀。在所有的形狀中,即使在最好的情況下,理論 FLOP 只占實(shí)際執(zhí)行 FLOP 的 2.74%,因此大多數(shù)計(jì)算都是多余的。類似地,調(diào)用另一個(gè) cuBLAS 內(nèi)核 maxwell_sgemmBatched_64x64_raggedMn_tn 也出現(xiàn)相同情況。

顯而易見,cuBLAS batch 矩陣相乘的執(zhí)行效率很低?;谶@個(gè)原因,我們在 NMT 中使用 TVM 生成高效的 batch 矩陣相乘內(nèi)核。

batch 矩陣相乘計(jì)算

在 TVM 中,普通 batch 矩陣相乘計(jì)算聲明如下:

# computation representation
A = tvm.placeholder((batch, M, K), name='A')
B = tvm.placeholder((batch, K, N), name='B')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute((batch, M, N),
        lambda b, y, x: tvm.sum(A[b, y, k] * B[b, k, x], axis = k),
        name = 'C')

調(diào)度優(yōu)化

在聲明計(jì)算之后,我們需要仔細(xì)地設(shè)計(jì)調(diào)度來更好地發(fā)揮性能。

調(diào)節(jié) block/線程數(shù)的參數(shù)

# thread indices
 block_y = tvm.thread_axis("blockIdx.y")
 block_x = tvm.thread_axis("blockIdx.x")
 thread_y = tvm.thread_axis((0, num_thread_y), "threadIdx.y")
 thread_x = tvm.thread_axis((0, num_thread_x), "threadIdx.x")
 thread_yz = tvm.thread_axis((0, vthread_y), "vthread", name="vy")
 thread_xz = tvm.thread_axis((0, vthread_x), "vthread", name="vx")

 # block partitioning
 BB, FF, MM, PP = s[C].op.axis
 BBFF = s[C].fuse(BB, FF)
 MMPP = s[C].fuse(MM, PP)
 by, ty_block = s[C].split(BBFF, factor = num_thread_y * vthread_y)
 bx, tx_block = s[C].split(MMPP, factor = num_thread_x * vthread_x)
 s[C].bind(by, block_y)
 s[C].bind(bx, block_x)
 vty, ty = s[C].split(ty_block, nparts = vthread_y)
 vtx, tx = s[C].split(tx_block, nparts = vthread_x)
 s[C].reorder(by, bx, vty, vtx, ty, tx)
 s[C].reorder(by, bx, ty, tx)
 s[C].bind(ty, thread_y)
 s[C].bind(tx, thread_x)
 s[C].bind(vty, thread_yz)
 s[C].bind(vtx, thread_xz)

我們?nèi)诤狭?batch 矩陣相乘的外部維度,例如 op 維的 BB 和 FF 在 batch 矩陣相乘計(jì)算中通常稱為「batch」維,我們用一個(gè)因子 (number_thread * vthread) 分割外部和內(nèi)部維度。

在 batch 矩陣相乘中不需要 Strided 模式,因此將虛擬線程數(shù)(vthready 和 vthreadx)都設(shè)置為 1。

找到 number_thread 的最佳組合

下面的結(jié)果是基于 NVIDIA M40 GPU(CUDA 8.0)。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

基于過去的經(jīng)驗(yàn),找到 num_thread_y 和 num_thread_x 最佳組合的方法是通過暴力搜索(brute-force search)。經(jīng)過暴力搜索后,可以找到當(dāng)前形狀的最佳組合,在當(dāng)前的計(jì)算中,num_thread_y = 8,num_thread_x = 32。

將 batch 矩陣相乘與其他運(yùn)算融合

現(xiàn)有的「黑盒」cuBLAS 庫調(diào)用一般會作為常用的「op 融合」優(yōu)化策略的邊界。然而,利用生成的高效 batch 矩陣相乘內(nèi)核,融合邊界極易被打破,將不僅僅是各個(gè)元素之間的融合,因此可以獲得更好的性能改進(jìn)。

從計(jì)算圖中可以看出,batch 矩陣相乘之后總是伴隨著廣播加法運(yùn)算或轉(zhuǎn)置運(yùn)算。

通過將「加法」或「轉(zhuǎn)置」運(yùn)算與 batch 矩陣相乘融合,可以減少內(nèi)核啟動開銷和冗余內(nèi)存訪問時(shí)間。

batch 矩陣相乘和廣播加法融合計(jì)算的聲明如下:

# computation representation
A = tvm.placeholder((batch_size, features, M, K), name='A')
# the shape of B is (N, K) other than (K, N) is because B is transposed is this fusion pattern
B = tvm.placeholder((batch_size, features, N, K), name='B')
ENTER = tvm.placeholder((batch_size, 1, M, N), name = 'ENTER')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute(
          (batch_size, features, M, N),
          lambda yb, yf, m, x: tvm.sum(A[yb, yf, m, k] * B[yb, yf, x, k], axis = k),
          name = 'C')
D = topi.broadcast_add(C, ENTER)

batch 矩陣相乘和轉(zhuǎn)置融合計(jì)算的聲明如下:

# computation representation
A = tvm.placeholder((batch_size, features, M, K), name='A')
B = tvm.placeholder((batch_size, features, K, N), name='B')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute(
          (batch_size, M, features, N),
          lambda yb, m, yf, x: tvm.sum(A[yb, yf, m, k] * B[yb, yf, k, x], axis = k),
          name = 'C')

融合內(nèi)核性能

測試生成代碼性能時(shí),形狀選擇為 [batch=64, heads=8, M=1, N=17, K=128]。選擇 17 作為序列長度是因?yàn)樗俏覀兩a(chǎn)中的平均輸入長度。

  • tf-r1.4 BatchMatmul: 513.9 us

  • tf-r1.4 BatchMatmul + Transpose (separate): 541.9 us

  • TVM BatchMatmul: 37.62 us

  • TVM BatchMatmul + Transpose (fused): 38.39 us

內(nèi)核融合優(yōu)化帶來了 1.7 倍的加速。

集成 TensorFlow

在我們的工作負(fù)載中,batch 矩陣相乘的輸入形狀是有限的,易于提前枚舉。有了這些預(yù)定義的形狀,我們可以提前生成高度優(yōu)化的 CUDA 內(nèi)核(固定形狀的計(jì)算可以帶來最佳優(yōu)化潛能)。同時(shí),還將生成一個(gè)適合大多數(shù)形狀的通用 batch 矩陣相乘內(nèi)核,為沒有提前生成內(nèi)核的形狀提供回退機(jī)制。

我們將生成的針對特定形狀的高效內(nèi)核和回退機(jī)制集成到 Tensorflow 中。我們開發(fā)了一些融合操作,例如 BatchMatMulTranspose 或 BatchMatMulAdd——使用 TVM runtime API 為確定輸入形狀啟動特定生成的內(nèi)核或調(diào)用回退內(nèi)核。

通過執(zhí)行圖優(yōu)化 pass,可以利用融合操作自動替換原始batch matmul + add/transpose。同時(shí),通過結(jié)合更激進(jìn)的圖優(yōu)化 pass,我們嘗試?yán)?TVM 為長尾操作模式生成更高效的融合內(nèi)核,以進(jìn)一步提升端到端性能。

總結(jié)

在阿里巴巴,我們發(fā)現(xiàn) TVM 是非常有效的開發(fā)高性能 GPU 內(nèi)核的工具,可以滿足我們的內(nèi)部需求。

在本博客中,我們以 Transformer 模型為例,說明了我們利用 TVM 的優(yōu)化策略。

首先,我們通過第一原理分析確定了 Transformer 模型的關(guān)鍵問題。然后,我們使用 TVM 生成高度優(yōu)化的 CUDA 內(nèi)核來取代 cuBLAS 版本(此時(shí)達(dá)到 13 倍的加速)。

接下來,利用 TVM 的內(nèi)核融合機(jī)制來融合 batch 矩陣相乘的前/后操作,以帶來進(jìn)一步的性能改進(jìn)(性能提升 1.7 倍)。端到端的性能改善達(dá)到 1.4 倍。基于這些生成的內(nèi)核,我們開發(fā)了一個(gè)圖優(yōu)化 pass,自動用 TVM 融合內(nèi)核替換掉原有的計(jì)算模式,確保優(yōu)化對終端用戶透明。

最后,所有這些優(yōu)化都以松散耦合的方式集成到 TensorFlow 中,這展示了將 TVM 與不同深度學(xué)習(xí)框架集成的潛在方式。

目前我們還有一項(xiàng)正在進(jìn)行的工作——將 TVM 整合為 TensorFlow 的 codegen 后端。我們希望將來與社群分享更多成果。

via:http://www.tvmlang.org

雷鋒網(wǎng) AI 研習(xí)社編譯整理。

雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。

阿里將 TVM 融入 TensorFlow,在 GPU 上實(shí)現(xiàn)全面提速

分享:
相關(guān)文章

編輯

關(guān)注AI學(xué)術(shù),例如論文
當(dāng)月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個(gè)人簡介
為了您的賬戶安全,請驗(yàn)證郵箱
您的郵箱還未驗(yàn)證,完成可獲20積分喲!
請驗(yàn)證您的郵箱
立即驗(yàn)證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說