• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    面向稀疏卷積神經(jīng)網(wǎng)絡(luò)的GPU 性能優(yōu)化方法?

    2020-11-03 12:26:20馮曉兵
    軟件學(xué)報(bào) 2020年9期
    關(guān)鍵詞:指令方法模型

    董 曉 , 劉 雷 , 李 晶 , 馮曉兵

    1(計(jì)算機(jī)體系結(jié)構(gòu)國家重點(diǎn)實(shí)驗(yàn)室(中國科學(xué)院 計(jì)算技術(shù)研究所),北京 100190)

    2(中國科學(xué)院大學(xué),北京 100190)

    深度神經(jīng)網(wǎng)絡(luò)近年來持續(xù)受到學(xué)術(shù)界和工業(yè)界的廣泛關(guān)注.自從2012 年AlexNet[1]在大規(guī)模圖像分類問題中展示出驚人的能力以來,研究人員持續(xù)通過在神經(jīng)網(wǎng)絡(luò)模型結(jié)構(gòu)和訓(xùn)練算法等領(lǐng)域的創(chuàng)新,借助日益增長的算力和大規(guī)模數(shù)據(jù)集,不斷提升神經(jīng)網(wǎng)絡(luò)在各類任務(wù)中的表現(xiàn).與此同時,眾多企業(yè)也將神經(jīng)網(wǎng)絡(luò)模型應(yīng)用到各種應(yīng)用中.比較典型的應(yīng)用包括物體檢測與識別[2,3]、自動駕駛[4]、機(jī)器翻譯[5]等.雖然這些模型在各類任務(wù)中展現(xiàn)出了驚人的精度,但這些模型會占用大量存儲空間,同時在執(zhí)行時伴隨著巨大的計(jì)算開銷.例如,用于圖像分類和物體檢測等計(jì)算機(jī)視覺應(yīng)用的ResNet50 網(wǎng)絡(luò)模型[6]包含超過2 500 萬個參數(shù),對一張形狀為224×224 的彩色圖像進(jìn)行分類,需要執(zhí)行76 億次運(yùn)算.另一方面,神經(jīng)網(wǎng)絡(luò)模型能力的進(jìn)步也依賴于模型規(guī)模的增長.早期用于簡單的手寫數(shù)字識別的LeNet5 模型[7]僅包含約6 萬個參數(shù),而對于在復(fù)雜的ImageNet[8]大規(guī)模圖像分類比賽中取得優(yōu)異表現(xiàn)的AlexNet 模型[1],其參數(shù)數(shù)目超過了6 千萬.龐大的參數(shù)規(guī)模和計(jì)算需求阻礙了神經(jīng)網(wǎng)絡(luò)模型的廣泛應(yīng)用,同時也使得實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的高效執(zhí)行成為了一個既有很強(qiáng)實(shí)際意義,同時也十分緊迫的問題.

    面對神經(jīng)網(wǎng)絡(luò)龐大的參數(shù)數(shù)目和海量的計(jì)算需求,研究人員提出了模型剪枝的方法來挖掘神經(jīng)網(wǎng)絡(luò)模型參數(shù)中的冗余性,對模型進(jìn)行簡化.由于被移除的參數(shù)不需要保留,同時與之相關(guān)的計(jì)算也可以省略,所以模型剪枝方法能夠有效降低神經(jīng)網(wǎng)絡(luò)模型的存儲開銷和計(jì)算需求.在保證剪枝后的模型在目標(biāo)任務(wù)上的精度損失在一定范圍內(nèi)的條件下,模型剪枝方法能夠從神經(jīng)網(wǎng)絡(luò)中識別出對最終精度影響不大的參數(shù),并將這些參數(shù)從網(wǎng)絡(luò)中移除,生成一個精簡的模型.在模型剪枝方法中,不對可移除參數(shù)的分布位置施加約束的非結(jié)構(gòu)化剪枝一般能夠最大限度地挖掘參數(shù)的冗余性.典型的非結(jié)構(gòu)化模型剪枝方法可以在精度幾乎沒有損失的情況下,移除模型中超過90%的參數(shù)[9-12],同時將剪枝后稀疏模型的計(jì)算需求降低為剪枝前的約10%.

    盡管非結(jié)構(gòu)化的模型剪枝方法有效降低了理論計(jì)算量,但在GPU 平臺上將這部分理論性能收益轉(zhuǎn)換為實(shí)際的性能加速卻面臨著嚴(yán)峻的挑戰(zhàn):首先,與剪枝前的稠密計(jì)算相比,剪枝后的稀疏計(jì)算的計(jì)算密度更低,這使得GPU 計(jì)算核心與DRAM 之間的數(shù)據(jù)傳輸容易成為性能瓶頸,導(dǎo)致剪枝后的稀疏計(jì)算難以充分利用GPU 的計(jì)算能力;其次,對于稀疏數(shù)據(jù),我們往往僅保留其中的非0 元素,并使用額外的索引結(jié)構(gòu)存儲這些元素的位置信息,以節(jié)約存儲空間.這兩部分共同構(gòu)成了稀疏數(shù)據(jù)的表達(dá),例如典型的稀疏矩陣格式CSR(compressed sparse row)[13],CSC(compressed sparse column),COO(coordinate)和稀疏張量格式CSF(compressed sparse fiber)[14]等.稀疏參數(shù)表示中的索引結(jié)構(gòu)增加了稀疏神經(jīng)網(wǎng)絡(luò)執(zhí)行時的訪存需求,進(jìn)一步惡化了計(jì)算密度低的問題.最后,GPU本身的執(zhí)行模型和存儲層次都比較復(fù)雜,而且目前已有的在GPU 上進(jìn)行稠密神經(jīng)網(wǎng)絡(luò)計(jì)算的cuDNN[15]和cuBLAS[16]等方法經(jīng)過了專家精心的手工優(yōu)化.因此,需要結(jié)合計(jì)算中的數(shù)據(jù)訪問特點(diǎn)和GPU 的體系結(jié)構(gòu)特征,對數(shù)據(jù)的布局和任務(wù)劃分等進(jìn)行相應(yīng)優(yōu)化,才能將稀疏計(jì)算的理論加速效果轉(zhuǎn)化為實(shí)際的性能收益.

    本文中,我們提出了一種稀疏感知的卷積算子代碼生成方法,能夠?yàn)榧糁笙∈璧木矸e神經(jīng)網(wǎng)絡(luò)生成高效的前向推理的執(zhí)行代碼.圖1 展示了我們方法的整個流程:首先,我們?yōu)榫矸e算子設(shè)計(jì)了算子模板.算子模板不考慮卷積參數(shù)的稀疏性.通過對算子模板的編譯和分析,我們建立卷積算子的中間表示模板.基于對中間表示模板的分析,我們可以建立卷積參數(shù)與中間表示中指令的映射關(guān)系.之后,通過結(jié)合具體的稀疏模型參數(shù),對中間表示模板進(jìn)行分析和變換,從中識別并刪除與無效參數(shù)相關(guān)的指令序列,獲得針對稀疏參數(shù)的算子代碼.中間表示模板可以在不同的稀疏參數(shù)間復(fù)用.另外,我們基于模型參數(shù)在神經(jīng)網(wǎng)絡(luò)執(zhí)行過程中取值固定的特點(diǎn),為模型參數(shù)和算子輸入設(shè)計(jì)了不同的訪問路徑,提升了執(zhí)行中的訪存吞吐量.同時,在生成的稀疏卷積算子代碼中,有效參數(shù)的位置信息已經(jīng)被隱式地編碼在代碼序列中,不再需要額外的索引結(jié)構(gòu),從而降低了運(yùn)行中的訪存需求,提升了稀疏算子的計(jì)算密度.我們將上述技術(shù)整合為一個框架,并使用公開的神經(jīng)網(wǎng)絡(luò)模型和數(shù)據(jù)集進(jìn)行了實(shí)驗(yàn).通過實(shí)驗(yàn),我們證明:相對于GPU 上已有的稠密執(zhí)行方法和稀疏執(zhí)行方法,本文所提出的方法能夠有效提升稀疏卷積神經(jīng)網(wǎng)絡(luò)的性能.

    總結(jié)來看,我們在本文中做出了以下貢獻(xiàn).

    (1) 我們提出了一種稀疏感知的卷積算子代碼生成方法.以我們設(shè)計(jì)的算子模板為起點(diǎn),我們建立了一種算子中間表示模板,基于中間表示模板的算法,能夠生成高效的稀疏卷積代碼;

    (2) 我們對稀疏卷積的內(nèi)存訪問設(shè)計(jì)了相應(yīng)的優(yōu)化方法.一方面,我們基于不同類型數(shù)據(jù)的訪問特征,將不同類型的數(shù)據(jù)映射到GPU 上不同的存儲空間,充分利用了GPU 的多種數(shù)據(jù)訪問路徑,提升了運(yùn)行時的訪存吞吐量;另一方面,我們將非0 參數(shù)的位置信息編碼在生成的代碼中,消除了稀疏數(shù)據(jù)索引部分的開銷,降低了運(yùn)行時的訪存需求;

    (3) 我們通過實(shí)驗(yàn)說明了所提出方法的有效性.在來自5 個卷積神經(jīng)網(wǎng)絡(luò)的10 個卷積算子上,當(dāng)稀疏程度達(dá)到0.9 時,我們的方法可以在批大小為64 時獲得相對cuBLAS 2.8 倍~41.4 倍、相對cuDNN 3.1 倍~9.6 倍、相對cuSPARSE 5.5 倍~43.2 倍以及相對Escoin 4.4 倍~39.5 倍的加速效果;在批大小為1 時,相對以上方法可以分別獲得1.2 倍~3.2 倍、1.2 倍~4.9 倍、2.4 倍~15.6 倍以及1.6 倍~11.2 倍的加速效果.與結(jié)構(gòu)化剪枝方法相比,我們也在類似的稀疏程度下展現(xiàn)了更好的性能收益.

    本文第1 節(jié)介紹相關(guān)背景知識,包括神經(jīng)網(wǎng)絡(luò)的剪枝方法以及GPU 體系結(jié)構(gòu).第2 節(jié)介紹本文的主要工作,包括算子和中間表示模板、稀疏感知的代碼生成算法以及優(yōu)化訪存瓶頸的技術(shù).第3 節(jié)通過實(shí)驗(yàn)說明本文提出方法的有效性,展示與已有工作的性能對比與分析結(jié)果以及對本方法相關(guān)開銷的分析.第4 節(jié)概括相關(guān)工作.第5 節(jié)總結(jié)本文并概括未來工作的方向.

    1 背景知識

    本節(jié)中,我們介紹與本文內(nèi)容相關(guān)的背景知識.我們首先介紹神經(jīng)網(wǎng)絡(luò)模型剪枝的相關(guān)概念;之后,我們介紹GPU 體系結(jié)構(gòu)的相關(guān)知識,重點(diǎn)關(guān)注GPU 的存儲層次.

    1.1 神經(jīng)網(wǎng)絡(luò)與模型剪枝

    神經(jīng)網(wǎng)絡(luò)(neural network)是機(jī)器學(xué)習(xí)算法的一種,它使用相互連接的算子,構(gòu)建將輸入數(shù)據(jù)映射到目標(biāo)輸出的數(shù)學(xué)模型.神經(jīng)網(wǎng)絡(luò)中的算子也常被稱為層,每個算子可能包含一些內(nèi)部參數(shù),并以之前的某些算子的輸出為輸入(第1 個算子使用整個網(wǎng)絡(luò)的輸入),進(jìn)行某種計(jì)算,產(chǎn)生輸出結(jié)果.在模型的訓(xùn)練過程中,通過調(diào)整各個算子中的參數(shù)的取值,可以使整個神經(jīng)網(wǎng)絡(luò)模型逼近我們期望建立的目標(biāo)函數(shù).在訓(xùn)練完成后,神經(jīng)網(wǎng)絡(luò)中的所有的參數(shù)取值都固定下來,并被部署到相應(yīng)的應(yīng)用中.使用訓(xùn)練完成的神經(jīng)網(wǎng)絡(luò)處理輸入數(shù)據(jù)的過程叫做前向推理(inference).

    根據(jù)使用算子類型的不同,神經(jīng)網(wǎng)絡(luò)可被進(jìn)一步分為主要使用卷積層的卷積神經(jīng)網(wǎng)絡(luò)(convolutional neural network)、主要使用全連接層的前饋神經(jīng)網(wǎng)絡(luò)(feedforward neural network)以及使用長短期記憶模塊的長短期記憶網(wǎng)絡(luò)(long short-term memory)等.本文中,我們主要關(guān)注卷積神經(jīng)網(wǎng)絡(luò).這一類網(wǎng)絡(luò)在計(jì)算機(jī)視覺領(lǐng)域的問題中已經(jīng)獲得了廣泛應(yīng)用,包括手寫字符識別、圖像分類和自動駕駛等.典型的卷積神經(jīng)網(wǎng)絡(luò)模型包括LeNet[7],AlexNet[1],VGG[17]和ResNet[6]等.卷積層的參數(shù)可以被抽象為一個4 維張量,4 個維度分別是卷積核維度、通道維度、高和寬.圖2 展示了一個包括2 個卷積核,每個卷積核包含2 個通道,寬和高為3 的卷積參數(shù)張量.

    盡管神經(jīng)網(wǎng)絡(luò)模型參數(shù)規(guī)模巨大,已有研究發(fā)現(xiàn):在訓(xùn)練完成的神經(jīng)網(wǎng)絡(luò)模型中,不同參數(shù)對模型最終精度的影響是不同的,存在相當(dāng)比例的冗余參數(shù),將其移除后,神經(jīng)網(wǎng)絡(luò)的精度不會發(fā)生明顯變化.基于這一發(fā)現(xiàn),研究人員提出了模型剪枝(model pruning)方法,從訓(xùn)練完成的神經(jīng)網(wǎng)絡(luò)中識別并刪除部分參數(shù),生成一個參數(shù)數(shù)目更少的輕量級稀疏模型.根據(jù)所刪除參數(shù)在原模型中的位置特點(diǎn),模型剪枝方法可以被分為結(jié)構(gòu)化剪枝[18-20]和非結(jié)構(gòu)化剪枝[11,21,22]兩類.結(jié)構(gòu)化剪枝方法考慮參數(shù)在原模型中的分布特點(diǎn),移除的參數(shù)不是隨機(jī)分布在原模型的任意位置,而是具有一定的結(jié)構(gòu).以卷積參數(shù)為例,結(jié)構(gòu)化剪枝方法以卷積核[19],或通道[18],或行、列[20]等為單位進(jìn)行剪枝.經(jīng)過結(jié)構(gòu)化剪枝獲得的模型,其參數(shù)往往仍然具有規(guī)則的結(jié)構(gòu)特點(diǎn),可以被視為規(guī)模更小的稠密參數(shù),因而通??梢灾苯邮褂冕槍Τ砻苡?jì)算的優(yōu)化庫進(jìn)行計(jì)算,所以一般不涉及稀疏計(jì)算問題.而非結(jié)構(gòu)化剪枝將每個參數(shù)作為剪枝的基本單位,獨(dú)立地對每個參數(shù)進(jìn)行剪枝,因而可以刪除任意位置的參數(shù).典型的方法包括Deep Compression[11],DNS[10],ADMM[9]等.這些方法基于某種規(guī)則判斷每個參數(shù)對最終精度的影響,識別出相對不重要的參數(shù)進(jìn)行移除.圖2 右側(cè)分別展示了非結(jié)構(gòu)化剪枝和結(jié)構(gòu)化剪枝的例子,其中,結(jié)構(gòu)化剪枝又包含以通道和卷積核為剪枝基本單位的情況.經(jīng)過非結(jié)構(gòu)化剪枝,非0 參數(shù)的分布沒有規(guī)律,模型參數(shù)變?yōu)椴灰?guī)則的稀疏張量(或稀疏矩陣),在稀疏模型上的計(jì)算也變成了稀疏模型參數(shù)與稠密輸入數(shù)據(jù)的計(jì)算.在GPU 上執(zhí)行時,需要借助cuSPARSE[23]或Escoin[24]等稀疏計(jì)算庫.由于非結(jié)構(gòu)化剪枝不對剪枝參數(shù)的分布做任何限制和假設(shè),所以往往能夠獲得相較于結(jié)構(gòu)化剪枝更好的壓縮效果[25,26],能夠更有效地降低模型的存儲開銷.目前的研究工作表明:非結(jié)構(gòu)化剪枝能夠?qū)崿F(xiàn)對典型的卷積神經(jīng)網(wǎng)絡(luò)模型參數(shù)9 倍~100 倍[9,10,22]的壓縮,有效地解決了神經(jīng)網(wǎng)絡(luò)模型參數(shù)規(guī)模過大的問題,同時也顯著降低了模型在推理過程中的計(jì)算需求.文獻(xiàn)[27]也按照剪枝粒度的不同,概述了當(dāng)前的模型剪枝工作.

    1.2 GPU體系結(jié)構(gòu)

    GPU 由于其高性能和高能效比的特點(diǎn),已經(jīng)在高性能計(jì)算和深度學(xué)習(xí)等領(lǐng)域獲得了廣泛應(yīng)用.GPU 一般包含多個流多處理器(streaming multiprocessor),每個流多處理器內(nèi)又包含眾多執(zhí)行核心(CUDA core).在GPU 程序載入時,GPU 線程按照用戶指定的配置被分層組織并綁定到具體的執(zhí)行核心上.線程首先被劃分為線程塊(thread block),線程塊綁定到流多處理器上.線程塊內(nèi)的線程綁定到相應(yīng)的流多處理器的執(zhí)行核心上執(zhí)行.在執(zhí)行時,GPU 線程以warp 為單位進(jìn)行調(diào)度.一個warp 包含相鄰的32 個線程.通過支持大量線程的并行執(zhí)行,GPU能夠提供很高的峰值性能.

    為了滿足大量線程執(zhí)行中的訪存需求,GPU 設(shè)計(jì)了復(fù)雜的存儲層次和訪存路徑,如圖3 所示.全局內(nèi)存基于DRAM,其存儲容量最大,一般在數(shù)十GB,用于存放GPU 程序的輸入和輸出數(shù)據(jù);但其訪存延遲比較高.對全局內(nèi)存的訪問一般會經(jīng)過高速緩存.二級高速緩存(L2 cache)由所有流多處理器共享,容量一般為數(shù)MB.一級高速緩存(L1 cache)位于流多處理器內(nèi)部,由位于同一個流多處理器上的線程共享,容量一般為數(shù)十KB.最快的存儲部件是寄存器.一個流多處理器一般集成了數(shù)萬個32 位寄存器.這些寄存器被劃分給不同的線程使用.另外,流多處理器上還有兩種比較特殊的存儲部件:共享內(nèi)存(shared memory)是一塊由編程人員手工控制使用的存儲空間,容量一般為數(shù)十KB,可以用于緩存程序執(zhí)行中頻繁訪問的數(shù)據(jù);而常量緩存(constant cache)可以用來緩存對常量內(nèi)存的訪問.常量內(nèi)存也位于DRAM 中,由編譯器和驅(qū)動程序使用,一般用于保存在整個GPU 程序生命周期中取值不變的數(shù)據(jù).當(dāng)常量緩存命中時,訪問延遲很低.對常量內(nèi)存的訪問往往不經(jīng)過高速緩存.常量緩存訪問的另一個特點(diǎn)是:當(dāng)一個warp 內(nèi)的線程訪問常量內(nèi)存中的相同位置時,這些線程的訪問請求會被合并,并通過一次請求獲得結(jié)果.

    2 稀疏感知的算子代碼生成

    本節(jié)介紹所提出的稀疏感知的算子代碼生成方法.我們首先介紹我們設(shè)計(jì)的算子模板,在模板設(shè)計(jì)中,我們考慮了多種針對GPU 平臺的優(yōu)化;接下來,我們介紹我們基于算子模板設(shè)計(jì)的中間表示模板以及基于中間表示模板的分析和稀疏算子代碼的生成過程;最后,我們分析了生成稀疏算子代碼中的訪存優(yōu)化.我們主要以卷積算子為例,具體說明我們的稀疏算子代碼生成過程.

    2.1 算子模板

    在GPU 平臺上有多種卷積的計(jì)算方法,包括基于矩陣乘法(GEMM)的方法和直接卷積等.基于GEMM 的方法需要對輸入數(shù)據(jù)進(jìn)行變換,這一過程需要對輸入數(shù)據(jù)進(jìn)行復(fù)制,增大了訪存需求.考慮到通用性和稀疏計(jì)算的計(jì)算密度問題,我們基于直接卷積的方式設(shè)計(jì)我們的卷積算子模板.我們首先定義要用到的符號.我們分別使用Input,Weight和Output表示輸入數(shù)據(jù)、卷積參數(shù)和卷積輸出,其中Input∈RN*C*H*W,Weight∈RK*C*R*S,Output∈RN*K*H′*W′.各個維度的含義見表1.維度的大小用大寫字母表示,而每個維度上的循環(huán)變量用相應(yīng)的小寫字母表示.同時,我們使用下標(biāo)表示某個具體位置的元素,如Inputn,c,h,w.

    Table 1 Definition of symbols in convolution表1 卷積中使用的符號定義

    我們沿卷積輸出結(jié)果Output的4 個維度進(jìn)行任務(wù)劃分.每個GPU 線程負(fù)責(zé)計(jì)算BN×BH×BW×BK大小的輸出結(jié)果,并且相鄰線程計(jì)算卷積輸出中相鄰位置的結(jié)果.其中,BN表示數(shù)據(jù)批維度每個線程計(jì)算任務(wù)的大小,BK表示卷積核維度每個線程計(jì)算任務(wù)大小,BH和BW分別表示在高和寬維度每個線程計(jì)算任務(wù)大小.這樣的任務(wù)劃分方式可以挖掘卷積計(jì)算過程中的數(shù)據(jù)重用機(jī)會.首先,計(jì)算Output上相鄰位置的結(jié)果時,使用的Input中的輸入數(shù)據(jù)之間可能存在重疊.這帶來了在不同線程之間重用輸入數(shù)據(jù)的機(jī)會.我們利用共享內(nèi)存實(shí)現(xiàn)在計(jì)算中對輸入數(shù)據(jù)的復(fù)用.一個線程塊內(nèi)的線程計(jì)算出需要使用的輸入數(shù)據(jù)區(qū)域,并共同將這部分?jǐn)?shù)據(jù)從全局內(nèi)存中讀出,寫入共享內(nèi)存.在后續(xù)計(jì)算中,每個線程根據(jù)自己的線程編號,從共享內(nèi)存中讀取相應(yīng)的數(shù)據(jù).這樣可以降低計(jì)算過程中訪問輸入數(shù)據(jù)的延遲.其次,計(jì)算Output不同位置的結(jié)果時,使用的卷積參數(shù)是相同的,所以Weight也可以被不同的線程復(fù)用.由于卷積參數(shù)的取值在整個計(jì)算過程中是固定不變的,所以卷積參數(shù)可以存儲在常量內(nèi)存中.同時,在計(jì)算時,不同的線程會同時訪問相同的參數(shù)進(jìn)行計(jì)算.因此,可以利用常量內(nèi)存訪問的合并機(jī)制降低訪存需求.算法1 展示了我們設(shè)計(jì)的卷積模板代碼,其中,blockIdx和threadIdx分別表示每個線程所在的線程塊和線程在線程塊內(nèi)的位置信息,結(jié)合任務(wù)劃分信息,每個線程可以計(jì)算出自己負(fù)責(zé)的計(jì)算區(qū)域.

    算法1.卷積模板代碼.

    輸入:Input,卷積輸入數(shù)據(jù);Weight,卷積參數(shù);

    輸出:Output,卷積計(jì)算結(jié)果.

    2.2 中間表示模板

    在算法1 中,每一個卷積參數(shù)Wk,c,r,s與相應(yīng)的輸入數(shù)據(jù)之間進(jìn)行乘法,乘法的結(jié)果累加起來,最終得到卷積計(jì)算的結(jié)果.在稀疏的情況下,這個過程中存在大量的冗余操作.具體來說,當(dāng)卷積參數(shù)具有稀疏性時,會存在Wk,c,r,s=0 的情況.此時,這個參數(shù)參與的乘法運(yùn)算便是冗余的,因?yàn)閯h除這些乘法指令并不會影響最終的結(jié)果.另外,由稀疏性帶來的冗余操作不僅局限于卷積參數(shù)直接參與的計(jì)算指令.對于輸入元素Inputn,c,h,w,如果與它進(jìn)行計(jì)算的所有參數(shù)取值都為0,那么對它的訪問也同樣是冗余的,相應(yīng)的訪存指令可以刪除.同樣地,如果計(jì)算某個卷積輸出結(jié)果涉及的全部參數(shù)取值均為0,那么對它的存儲操作也是冗余的.因此,如果從稠密的卷積計(jì)算中識別并刪除由稀疏參數(shù)造成的冗余指令,便可以獲得針對稀疏參數(shù)的卷積代碼.我們的稀疏算子代碼生成方法就基于刪除冗余操作指令的思想.

    為了實(shí)現(xiàn)冗余指令的識別和刪除,我們需要解決以下幾個問題:第一,需要建立一種算子的中間表示,這種中間表示能夠支持分析模型參數(shù)與計(jì)算指令的對應(yīng)關(guān)系;其次,中間表示需要支持快速準(zhǔn)確的指令依賴分析;最后,由于相同的算子可能被用在不同的神經(jīng)網(wǎng)絡(luò)中,對應(yīng)不同的稀疏參數(shù)取值,所以該中間表示應(yīng)該能夠作為模板,適配不同的稀疏參數(shù),并生成相應(yīng)的代碼.

    面對上面的問題,我們設(shè)計(jì)了一種算子中間表示.該中間表示基于英偉達(dá)PTX(parallel thread execution)形式.PTX 是英偉達(dá)設(shè)計(jì)的一套虛擬的體系結(jié)構(gòu)和指令集,而且是GPU 程序編譯過程中的中間結(jié)果.圖4 展示了GPU 程序使用英偉達(dá)nvcc 編譯器的編譯過程以及各階段輸出結(jié)果的形式.

    下面分別介紹該算子中間表示如何解決上面的3 個問題.首先是建立每個模型參數(shù)與依賴的指令序列之間映射的問題.在算法1 中,每個卷積參數(shù)可以由作為下標(biāo)的循環(huán)變量k,c,r,s唯一確定,而同時,循環(huán)變量也可以確定一次迭代中具體的計(jì)算.所以,一個直接的策略就是通過循環(huán)變量將卷積涉及的乘累加(fused multiply-add,簡稱FMA)指令與對應(yīng)的卷積參數(shù)聯(lián)系起來.但是在后續(xù)編譯器的指令調(diào)度過程中,編譯器可能會對指令的順序進(jìn)行調(diào)整.所以在最終生成的代碼中,乘累加指令出現(xiàn)的順序與循環(huán)遍歷的順序是不一致的.我們需要設(shè)計(jì)新的機(jī)制,將卷積參數(shù)與對應(yīng)的指令關(guān)聯(lián)起來.考慮到模型參數(shù)和GPU 指令兩方面的特點(diǎn),我們采用了一種基于參數(shù)取值的關(guān)聯(lián)機(jī)制.GPU 的代數(shù)運(yùn)算指令通常有一種直接編碼立即數(shù)操作數(shù)的形式,例如,圖5 展示了編碼了立即數(shù)的單精度浮點(diǎn)數(shù)乘累加指令FFMA,指令FFMAR3,Ri,1.2,R2表示執(zhí)行R3=Ri×1.2+R2的計(jì)算,作為操作數(shù)之一的立即數(shù)1.2 會直接編碼在指令中.這種形式的指令能夠?qū)⑴c計(jì)算的數(shù)據(jù)與指令直接關(guān)聯(lián)起來.

    在此之上,我們再建立卷積參數(shù)位置與參數(shù)取值之間的映射.具體來說,我們隨機(jī)生成取值不相同且非0 的模板參數(shù),取值不同保證了由參數(shù)取值可以唯一確定參數(shù)的位置.在編譯卷積算子模板的過程中,我們將模板參數(shù)作為立即數(shù)提供給編譯器;同時,我們將涉及模型參數(shù)的循環(huán)進(jìn)行展開,使得這些參數(shù)被編碼到相應(yīng)的計(jì)算指令中.這樣,通過解析指令中立即數(shù)的取值,便可以唯一確定參數(shù)的位置.同時,循環(huán)展開消除了循環(huán)控制相關(guān)指令,也給編譯器更大的空間進(jìn)行指令調(diào)度等優(yōu)化,有利于編譯器生成性能更好的代碼.由于循環(huán)展開會導(dǎo)致指令數(shù)目增多,使得編譯生成的文件增大.我們在第3.7 節(jié)對編譯生成的文件體積以及循環(huán)展開對運(yùn)行時指令獲取的影響進(jìn)行了分析.

    PTX 也適合進(jìn)行高效的指令間依賴關(guān)系分析.PTX 程序符合靜態(tài)單賦值(SSA)的形式,且使用虛擬寄存器.PTX 代碼中使用的每個寄存器都有唯一的一次定值,因此建立寄存器之間的依賴關(guān)系十分簡單.通過解析指令中的寄存器的名字,我們可以高效地追蹤指令之間的依賴關(guān)系.最后,由于我們生成的是不含0 的模板參數(shù),所以每個模型參數(shù)可能涉及的指令都被保留在了中間表示模板中.所以不論具體的稀疏參數(shù)如何,該中間表示都能用于生成對應(yīng)的稀疏程序.圖5 展示了對應(yīng)的模板中間表示的例子.

    2.3 稀疏算子代碼生成

    基于算子的中間表示模板,我們設(shè)計(jì)了結(jié)合具體的稀疏參數(shù)生成對應(yīng)稀疏卷積代碼的算法.稀疏算子代碼生成算法主要完成兩項(xiàng)工作:首先是將模板參數(shù)替換為真實(shí)的稀疏參數(shù),保證計(jì)算過程中使用參數(shù)的正確性;第二是識別由稀疏參數(shù)帶來的冗余指令,并對其進(jìn)行刪除;同時,還需要維護(hù)由于刪除指令導(dǎo)致的寄存器依賴關(guān)系的變化,以保證程序的正確性.以上工作通過對PTX 中間表示模板的遍歷完成,該算法的偽代碼見算法2.

    算法2.稀疏算子代碼生成算法.

    輸入:ptxTemp,中間表示模板;paramTemp,模板參數(shù);paramReal,真實(shí)稀疏參數(shù);

    輸出:ptxCode,為真實(shí)稀疏參數(shù)生成的PTX 代碼.

    在對指令的遍歷過程中,算法使用了2 個哈希表記錄相關(guān)狀態(tài).valueMap用于將模板參數(shù)取值映射到真實(shí)的稀疏卷積參數(shù).regMap用于處理由于冗余指令刪除帶來的寄存器依賴關(guān)系的變化,它記錄了等價寄存器的映射關(guān)系.對于中間表示中的每一條PTX 指令,算法首先通過解析識別指令的具體類型和各個組成部分,這由字符串匹配完成.對于乘累加指令FFMA,我們首先檢查是否需要修改指令的源寄存器,并通過查詢valueMap對指令中的立即數(shù)進(jìn)行替換.例如,對圖5 中的第1 條FFMA 指令FFMAR3,Ri,1.2,R2,經(jīng)過查詢valueMap,模板參數(shù)1.2被替換為真實(shí)參數(shù)0,并且由于regMap為空,不需要進(jìn)行源寄存器替換.同時,由于替換后立即數(shù)操作數(shù)為0,這條指令實(shí)際上進(jìn)行了R3=R2的操作,因此R3和R2實(shí)際上是等價的.如果能夠?qū)⒑罄m(xù)對R3寄存器的引用替換為對R2的引用,那么這條FFMA 指令便可以刪除(圖5 中使用橫線標(biāo)注).我們在regMap中記錄R3→R2的映射關(guān)系,并刪除這條指令.由于稀疏卷積參數(shù)涉及的指令為FFMA 指令,被等價映射的寄存器為保存卷積計(jì)算臨時結(jié)果的寄存器,這些寄存器會被后面的FFMA 指令作為源操作數(shù)使用.由于對寄存器的引用一定出現(xiàn)在寄存器的定值之后,因此我們通過查詢當(dāng)前regMap中記錄的寄存器映射關(guān)系,便可以實(shí)現(xiàn)相應(yīng)的修改.當(dāng)在后面的指令中遇到對R3的引用時,例如圖5 中的FFMARd,Rj,1.4,R3,由于regMap中已經(jīng)記錄了R3到R2的映射,因此可以正確地將對R3的引用修改為對R2的引用.通過使用regMap記錄寄存器的映射關(guān)系,我們可以刪除使用0 的FFMA計(jì)算指令.另外,寄存器映射關(guān)系也會影響存儲指令.因?yàn)槌死奂又噶畹哪康募拇嫫鞅4媪司矸e計(jì)算的結(jié)果,因此會作為存儲指令的源操作數(shù).對于存儲指令ST,我們也檢查其源寄存器(保存待寫出值的寄存器)是否被重命名,并進(jìn)行必要的修改.算法沒有對可能存在的冗余訪存指令進(jìn)行顯式的刪除操作,這主要是基于對GPU 的訪存指令特點(diǎn)的考慮.GPU 通常支持多種寬度不同的訪存指令,例如32 位、64 位等,并且不同寬度的指令能夠?qū)崿F(xiàn)的訪存吞吐量不同[28].當(dāng)多個元素的訪問被打包到同一條訪存指令中時,刪除其中某個元素的訪問,并將其拆分為多條寬度更小的訪存指令,可能會影響訪存吞吐量.因此,我們沒有對訪存指令進(jìn)行直接刪除,而是交給后續(xù)的匯編器ptxas 決定,是否對涉及未被引用操作數(shù)的訪存指令進(jìn)行修改.

    我們設(shè)計(jì)的稀疏代碼生成算法的復(fù)雜度是O(n),其中,n為中間表示模板的指令條數(shù).對于每條指令,我們進(jìn)行解析和哈希表查找的操作.解析基于字符串匹配進(jìn)行,而哈希表的查找也可以快速實(shí)現(xiàn).綜合來說,稀疏代碼生成算法的時間效率較好.

    完成冗余指令刪除后,我們就獲得了針對稀疏卷積參數(shù)的PTX 程序.接下來,該P(yáng)TX 程序經(jīng)過匯編器ptxas優(yōu)化(如圖4 所示),獲得最終的二進(jìn)制代碼.由于PTX 面向英偉達(dá)設(shè)計(jì)的虛擬GPU 體系結(jié)構(gòu),基于PTX 的中間表示可以為不同體系結(jié)構(gòu)的GPU 生成最終的二進(jìn)制代碼(通過為ptxas 匯編器提供不同的參數(shù),指定具體的目標(biāo)GPU 平臺).另外,ptxas 會負(fù)責(zé)執(zhí)行與具體GPU 體系結(jié)構(gòu)相關(guān)的優(yōu)化,包括寄存器分配和指令調(diào)度等,所以我們生成的稀疏算子程序也能夠受益于這些優(yōu)化.最后,由于PTX 中間表示模板可以在不同的稀疏模型參數(shù)上復(fù)用,相當(dāng)于降低了獲得中間表示模板的開銷.我們通過實(shí)驗(yàn)發(fā)現(xiàn),圖4 中的前兩個編譯階段(從cu 文件到ptx 文件)占用了編譯過程的大部分時間(90%以上),所以選用PTX 作為中間表示層次可以復(fù)用開銷最大的編譯過程,降低后續(xù)生成具體稀疏算子代碼的時間開銷.在實(shí)驗(yàn)中,ptxas 編譯生成的ptx 代碼所需的時間在幾十到幾百毫秒.

    2.4 訪存優(yōu)化

    盡管GPU 能夠提供強(qiáng)大的峰值計(jì)算性能,但達(dá)到峰值性能需要程序具有較高的計(jì)算訪存比.訪存密集型的應(yīng)用很容易受到訪存帶寬的限制,難以實(shí)現(xiàn)滿意的性能.我們通過roofline 模型[29]分析了不同計(jì)算密度下,GPU程序的性能上限,如圖6 所示.橫軸表示不同的計(jì)算密度,單位是操作數(shù)/字節(jié),表示從全局內(nèi)存訪問的每字節(jié)數(shù)據(jù)所參與的操作數(shù)目.縱軸表示性能,使用每秒鐘可執(zhí)行的操作數(shù)目衡量.圖中的折線表示在每個計(jì)算密度下能夠達(dá)到的峰值性能.如果一個程序的計(jì)算密度在折線拐點(diǎn)的左側(cè),則該程序的峰值性能是訪存受限的;如果程序位于拐點(diǎn)右側(cè),則該程序是計(jì)算受限的.我們選取了3 種不同的GPU,并標(biāo)注了每個GPU 的峰值性能和達(dá)到峰值性能所需要的計(jì)算密度的下限.其中,Tesla K40m 和Titan Xp 是工作站級別的GPU,而Jetson TX2 是面向終端設(shè)備的GPU.可以看到:計(jì)算能力更強(qiáng)的GPU,其對計(jì)算密度的要求往往也越高.

    我們對稀疏參數(shù)卷積的計(jì)算密度進(jìn)行了分析.假設(shè)卷積參數(shù)Weight的稀疏程度(取值為0 的參數(shù)在全部參數(shù)中所占的比例)為p.對于經(jīng)過非結(jié)構(gòu)化剪枝的稀疏參數(shù),取值為0 的元素的分布沒有規(guī)律,我們認(rèn)為對任意位置(k,c,r,s),其取值為0 的概率P(Weightk,c,r,s=0)=p,則計(jì)算密度OI(operational intensity)可以用公式(1)表示:

    其中,T表示輸入數(shù)據(jù)、輸出結(jié)果和模型參數(shù)的數(shù)據(jù)類型,sizeof(T)為常數(shù).當(dāng)稀疏程度p=0 時,公式(1)對應(yīng)稠密卷積的情況.很容易從公式(1)中看出:隨著稀疏程度p增大,計(jì)算密度OI會逐漸降低,使得訪存容易成為瓶頸.因此在稀疏場景下,優(yōu)化GPU 程序的訪存具有重要價值.

    與一般的GPU 稀疏程序優(yōu)化相比,由稀疏代碼生成算法生成的卷積程序采用了兩種技術(shù)優(yōu)化訪存.

    首先,我們充分利用了神經(jīng)網(wǎng)絡(luò)稀疏參數(shù)在編譯時取值確定的特點(diǎn),將稀疏模型參數(shù)和輸入數(shù)據(jù)存儲在不同的存儲空間,并通過不同的訪問路徑進(jìn)行訪問.直接編碼在PTX 指令中的常數(shù)會存儲在GPU 常量內(nèi)存中,而卷積輸入數(shù)據(jù)則位于全局內(nèi)存中.一方面,我們充分利用了GPU 提供的多種訪存路徑(圖3),輸入數(shù)據(jù)由全局內(nèi)存經(jīng)過高速緩存達(dá)寄存器,并被存儲在共享內(nèi)存中反復(fù)使用.計(jì)算結(jié)果通過高速緩存寫入全局內(nèi)存.而取值固定的模型參數(shù)存儲在常量內(nèi)存中,經(jīng)過片上的常量緩存進(jìn)行訪問.另一方面,對模型參數(shù)和輸入數(shù)據(jù)使用不同的訪存路徑,避免了彼此之間在高速緩存的干擾.以Tesla K40m GPU 為例,每個流多處理器對應(yīng)的二級高速緩存空間一般僅有100KB.假設(shè)有1 024 個線程活躍,則每個線程平均只有100 字節(jié)的高速緩存空間,在單精度浮點(diǎn)數(shù)的情況下,對應(yīng)25 個浮點(diǎn)數(shù).算法1 中,在兩次對相同的模型參數(shù)Wk,c,r,s的訪問之間,我們需要訪問channel×R×S個輸入數(shù)據(jù)元素(為了隱藏全局內(nèi)存的訪問延遲,在執(zhí)行當(dāng)前計(jì)算時,會同時讀取下一輪計(jì)算需要的數(shù)據(jù)).在真實(shí)的神經(jīng)網(wǎng)絡(luò)中,這個規(guī)模遠(yuǎn)超過了每個線程對應(yīng)的高速緩存的空間.因此,如果對模型參數(shù)和輸入數(shù)據(jù)使用相同的訪問路徑,將會損害數(shù)據(jù)局部性,造成訪存吞吐量的降低.

    第2 個優(yōu)化來源于我們對非0 元素位置信息的編碼方式.一般的稀疏程序采用某種稀疏格式表達(dá)稀疏數(shù)據(jù),非0 元素的取值與位置信息被分別存儲.例如流行的CSR 格式,非0 元素的值存儲在數(shù)組values中;每個非0元素的列號被單獨(dú)存儲在一個數(shù)組colIdx中,同時,每一行對應(yīng)的非0 元素在values數(shù)組中的起始位置被記錄在數(shù)組rowPtr中.公式(2)計(jì)算了采用CSR 格式時,位置信息占用的空間Slocation:

    其中,m表示稀疏矩陣的行數(shù),具體取值取決于將Weight展開成矩陣的方式.非0 元素取值所占空間Svalue可用公式(3)計(jì)算:

    為了衡量位置信息所占用空間的比重,我們計(jì)算Slocation與Svalue的比值,如公式(4)所示:

    第1 項(xiàng)取決于存儲非0 元素列號與存儲非0 元素取值所使用的數(shù)據(jù)類型.在實(shí)際的神經(jīng)網(wǎng)絡(luò)模型中,稀疏矩陣的列的寬度可能超過256,所以非0 元素列號至少需要16 比特才能表示.對于每行的起始位置,其類型取決于整個矩陣中非0 元素的數(shù)目,即(1-p)×K×C×R×S,一般也至少需要16 比特表示.對于非0 元素的取值,我們一般使用32 比特單精度浮點(diǎn)數(shù)表示,則公式(4)中的第1 項(xiàng)取值至少為0.5.因此,與非0 元素取值所占用的空間相比,位置信息所占用的空間至少會超出其一半的大小.而在當(dāng)前GPU 上的稀疏計(jì)算庫[23]中,這一項(xiàng)的值為1.因此,非零元素位置信息所占用的空間是不能忽略的.在文獻(xiàn)[25,26]中也提到了存儲稀疏模型時,位置信息會帶來額外的開銷,并對性能造成負(fù)面影響.

    我們生成的稀疏算子程序能夠避免位置信息的訪存開銷.由于在編譯時我們展開了與模型參數(shù)相關(guān)的循環(huán),并在稀疏代碼生成階段將真實(shí)的稀疏模型參數(shù)取值編碼到了指令中,在生成的代碼中,每個參數(shù)已經(jīng)按照自己的位置與對應(yīng)的輸入數(shù)據(jù)進(jìn)行計(jì)算,所以生成的稀疏程序不再需要額外的位置信息,避免了程序運(yùn)行時對位置信息的訪問,降低了訪存需求.

    3 實(shí)驗(yàn)分析

    在本節(jié)中,我們希望通過實(shí)驗(yàn)回答與本文所提出的稀疏感知的代碼生成方法相關(guān)的3 個關(guān)鍵問題.

    · 首先是該方法的有效性如何,即:本文的方法是否能夠改進(jìn)稀疏卷積的計(jì)算性能?

    · 第2 個問題與該方法的稀疏適應(yīng)性相關(guān),即:在不同稀疏程度下,本文方法生成的稀疏卷積代碼性能如何變化?

    · 最后一個問題關(guān)注本方法的開銷.為了進(jìn)行冗余指令刪除以及使用常量內(nèi)存等優(yōu)化,我們對代碼進(jìn)行了循環(huán)展開,使得指令數(shù)目顯著增加.我們希望通過實(shí)驗(yàn)確定,指令數(shù)目膨脹對代碼體積和指令訪問產(chǎn)生了什么樣的影響.

    我們通過實(shí)驗(yàn)逐一回答上面的問題.在第3.1 節(jié)中,我們首先介紹實(shí)驗(yàn)配置,包括對比方法、實(shí)驗(yàn)使用的卷積算子信息以及實(shí)驗(yàn)平臺等.第3.2 節(jié)~第3.5 節(jié)從不同角度說明本文方法的有效性.其中,第3.2 節(jié)和第3.3 節(jié)通過在實(shí)驗(yàn)卷積算子上的性能對比和分析,展示相對其他方法的性能優(yōu)勢.第3.2 節(jié)主要關(guān)注稠密計(jì)算方法和其他非結(jié)構(gòu)化稀疏優(yōu)化方法,而第3.3 節(jié)探索了與結(jié)構(gòu)化剪枝方法的性能對比問題.第3.4 節(jié)和第3.5 節(jié)分別對冗余指令刪除和訪存路徑優(yōu)化這兩個主要的優(yōu)化技術(shù)的直接效果進(jìn)行了分析.第3.6 節(jié)回答稀疏適應(yīng)性的問題,我們評估了不同稀疏程度下本方法生成代碼的性能,并與其他方法進(jìn)行了對比分析.第3.7 節(jié)針對開銷問題,具體分析了生成代碼體積的變化和對指令訪問的影響.

    3.1 實(shí)驗(yàn)配置

    我們在一臺配有英偉達(dá)Tesla K40m 的服務(wù)器上進(jìn)行實(shí)驗(yàn).Tesla K40m 具有15 個流多處理器,顯存容量為12GB.默認(rèn)情況下,每個流多處理器上有16KB 的一級高速緩存和48KB 的共享內(nèi)存.另外,每個流多處理器還有8KB 的常量緩存,用于緩存對卷積參數(shù)的訪問.所有流多處理器共享容量為1536KB 的二級高速緩存.

    為了盡可能覆蓋在卷積神經(jīng)網(wǎng)絡(luò)中使用的各種參數(shù)規(guī)模和計(jì)算量不同的卷積算子,我們從流行的卷積神經(jīng)網(wǎng)絡(luò)中選擇了10 個有代表性的算子,作為實(shí)驗(yàn)中進(jìn)行優(yōu)化的對象.實(shí)驗(yàn)中使用的算子的具體信息見表2,我們在表中列出了每一個算子的具體信息.可以看到:我們選取的算子覆蓋了僅需要36M 計(jì)算的簡單算子,也包含需要236G 計(jì)算的復(fù)雜算子.參數(shù)最少的算子僅包含500 個參數(shù),而最大的算子包含超過14 萬個參數(shù).在實(shí)驗(yàn)中使用的批大小為64 和1.在執(zhí)行生成的代碼時,對于每一個算子,我們根據(jù)輸出張量形狀和任務(wù)劃分信息計(jì)算出加載CUDA kernel 時的線程塊與線程的形狀.

    Table 2 Convolution operators used in experiments表2 實(shí)驗(yàn)中使用的卷積算子信息

    為了說明我們提出方法的有效性,我們選取了多種在GPU 上執(zhí)行卷積神經(jīng)網(wǎng)絡(luò)的方法作為對比對象.這些對比對象可以分為兩大類.

    · 第1 類是不利用參數(shù)中稀疏性的方法,包括cuDNN[15]和cuBLAS[16].cuDNN 內(nèi)封裝了多種優(yōu)化的卷積實(shí)現(xiàn),并且會在運(yùn)行時根據(jù)輸入數(shù)據(jù)規(guī)模和具體平臺等信息選擇最優(yōu)實(shí)現(xiàn).cuBLAS 中的Sgemm 被用來實(shí)現(xiàn)卷積,我們使用了基于矩陣展開的卷積方法,并將第1 步輸入張量展開和第2 步矩陣乘法的總時間作為cuBLAS 方法的執(zhí)行時間.另外,雖然結(jié)構(gòu)化剪枝一般并不造成稀疏計(jì)算的問題,考慮到其也是一類利用神經(jīng)網(wǎng)絡(luò)參數(shù)冗余性,加速神經(jīng)網(wǎng)絡(luò)執(zhí)行的方法,我們也將其選做對比方法,并使用cuDNN 實(shí)現(xiàn)結(jié)構(gòu)化剪枝后的計(jì)算.我們選擇了通道剪枝[18]和卷積核剪枝[19]兩個結(jié)構(gòu)化剪枝方法進(jìn)行對比:對于通道剪枝,我們比較刪除卷積操作一半輸入通道的情況;對于卷積核剪枝,比較刪除一半卷積核的情況.此外,由于卷積核數(shù)目減半會導(dǎo)致卷積結(jié)果的通道數(shù)為之前的一半,使得后續(xù)卷積的輸入通道數(shù)目減少,因此我們也考慮了同時將輸入通道和卷積核數(shù)目減半的情況.雖然不考慮利用參數(shù)的稀疏性,但cuDNN 和cuBLAS 經(jīng)過專家的精心調(diào)優(yōu),可以實(shí)現(xiàn)非常好的性能;

    · 另一類方法是與本文工作目的相同,同樣可以進(jìn)行稀疏神經(jīng)網(wǎng)絡(luò)計(jì)算的方法.我們選擇了Escoin[24]和cuSPARSE[23]進(jìn)行對比.對于cuSPARSE,我們使用與cuBLAS 類似的方法,基于cuSPARSE 中的稀疏-稠密矩陣乘法實(shí)現(xiàn)卷積,并考慮輸入張量展開的時間;Escoin 也提供了稀疏卷積的GPU 優(yōu)化實(shí)現(xiàn),我們從github 上下載了它的代碼.

    實(shí)驗(yàn)中使用的cuDNN,cuBLAS 和cuSPARSE 的版本分別為7.6.5,9.0 和9.0.Escoin 使用了當(dāng)前的最新版本(github commit e89275f961847319e6b0331f0dc163a3293fad4c).實(shí)驗(yàn)在英偉達(dá)GPU 編程環(huán)境CUDA 9.0 下進(jìn)行,使用nvcc 9.0 編譯器編譯代碼.

    3.2 與稀疏和稠密卷積方法的對比分析

    在這一節(jié)中,我們分析我們的優(yōu)化方法對其他可用于稀疏卷積優(yōu)化執(zhí)行的方法的性能收益.大部分模型剪枝工作沒有詳細(xì)給出每一層的壓縮比例,考慮到已有模型壓縮工作在實(shí)驗(yàn)中所涉及的模型上均實(shí)現(xiàn)了超過10倍的壓縮,我們在本節(jié)中使用0.9 的稀疏程度進(jìn)行性能測試.在第3.6 節(jié)中,我們進(jìn)一步分析了不同稀疏程度下的性能.我們使用在每個算子上執(zhí)行10 次的平均時間表示每個方法的性能.圖7 和圖8 分別展示了批大小為64和批大小為1 時的實(shí)驗(yàn)結(jié)果.我們計(jì)算了本文方法生成的算子對其他方法的加速比:數(shù)值大于1 表示我們的方法性能更優(yōu),小于1 表示對比方法的性能更好.

    我們從幾個不同的角度對實(shí)驗(yàn)結(jié)果進(jìn)行分析.從不同的對比方法看:

    首先,在所有的對比方法中,cuSPARSE 幾乎在所有的卷積算子上的性能都是最差的,這反映了對GPU 平臺上的稀疏計(jì)算進(jìn)行優(yōu)化的難度.即使在0.9 的稀疏程度下,其性能也難以達(dá)到精心調(diào)優(yōu)的稠密計(jì)算庫的水平.盡管cuBLAS 和cuDNN 不考慮稀疏參數(shù)帶來的優(yōu)化機(jī)會,但規(guī)則的訪存模式和細(xì)致的手工調(diào)優(yōu),仍然能夠?qū)崿F(xiàn)很好的性能.與對比方法相比,我們生成的稀疏算子代碼在所有的卷積上都展現(xiàn)了超過其他所有方法的性能.具體來說,在批大小為64 時,相對于cuBLAS,cuDNN,cuSPARSE 和Escoin,我們的方法分別實(shí)現(xiàn)了2.8 倍~41.4 倍、3.1 倍~9.6 倍、5.5 倍~43.2 倍和4.4 倍~39.5 倍的加速比;在批大小為1 時,相對cuBLAS,cuDNN,cuSPARSE 和Escoin 的加速比范圍分別為1.2 倍~3.2 倍、1.2 倍~4.9 倍、2.4 倍~154.6 倍和1.6 倍~11.2 倍.考慮到cuBLAS和cuSPARSE 方法基于矩陣展開實(shí)現(xiàn),將輸入張量展開的時間包含在內(nèi).為了更細(xì)致地比較計(jì)算部分的性能,我們進(jìn)一步對cuBLAS和cuSPARSE 方法的性能進(jìn)行了分解,計(jì)算輸入張量展開部分在總時間中所占的比例.對于cuBLAS,在批大小為64 和批大小為1 時,展開輸入張量的時間在10 個算子上平均所占比例分別為3.16%和6.22%.具體來看:當(dāng)批大小為 64 時,占比為 0.11%~12.69%;批大小為 1 時,占比總體來看有所上升,為0.32%~16.91%.對于cuSPARSE,由于其第2 步矩陣乘法的性能顯著差于cuBLAS,因此輸入張量展開時間占比更低.批大小為64 時不超過9.01%,平均為1.62%;批大小為1 時不超過11.26%,平均為2.07%.相對于cuDNN,生成的稀疏算子均獲得了顯著的加速效果.上面的實(shí)驗(yàn)結(jié)果說明:相比于現(xiàn)有的稀疏神經(jīng)網(wǎng)絡(luò)執(zhí)行方法,我們所提出的方法能夠有效利用壓縮后的稀疏模型參數(shù),加速網(wǎng)絡(luò)執(zhí)行.

    其次,優(yōu)化效果也與算子本身的特征以及批大小有關(guān).批大小為64 時,除lenet-conv1 以外,我們的方法對cuDNN 的加速效果在不同算子間比較穩(wěn)定.我們通過profiling 發(fā)現(xiàn):雖然cuDNN 對lenet-conv1 和lenet-conv2均采用了 fft 算法,但內(nèi)部使用了不同的 kernel 實(shí)現(xiàn)(lenet-conv1:cgemm_strided_batched_ sm35_ldg_nt_64x8x64x16x16;lenet-conv2:fermiPlusCgemmLDS128_batched),造成了明顯的性能差異.盡管lenet-conv1 的計(jì)算需求僅為lenet-conv2 的約18%,但執(zhí)行時間卻是lenet-conv2 的1.3 倍.另外,cuBLAS 中的矩陣乘法kernel 在計(jì)算量較大的5 個算子(2 個resnet 算子和3 個vgg 算子)上的性能顯著好于剩余的計(jì)算量較小的5 個算子,平均性能差異可達(dá)12.6 倍.因此,我們的方法相對cuBLAS 的加速效果對于小規(guī)模算子更加明顯.cuSPARSE和Escoin也有類似的現(xiàn)象,在計(jì)算量較大的算子和其他算子上的平均性能有顯著的差異.

    批大小為1 時,卷積參數(shù)失去了在不同輸入數(shù)據(jù)之間的復(fù)用機(jī)會.第1 次讀取卷積參數(shù)會導(dǎo)致片上的常量緩存發(fā)生缺失,需要從位于片外DRAM 上的常量內(nèi)存中進(jìn)行讀取,延遲很高.而當(dāng)批大小為64 時,這一開銷可以被后續(xù)通過常量緩存的加速訪問分?jǐn)?因此總體來看,批大小為1 時的性能收益較64 時有所下降.在3 個來自vgg 的算子上,我們的方法取得收益更加明顯.這是因?yàn)関gg 算子的計(jì)算結(jié)果規(guī)模很大,經(jīng)過任務(wù)劃分后允許更多GPU 線程并發(fā)執(zhí)行,所以可以通過線程級并行更好地掩蓋訪存延遲;resnet 算子雖然訪問的參數(shù)規(guī)模與vgg算子類似,但由于計(jì)算結(jié)果規(guī)模顯著小于vgg 算子,因此線程級并行機(jī)會更少.其他算子雖然卷積參數(shù)數(shù)目較少,但其輸出結(jié)果規(guī)模也遠(yuǎn)小于vgg 算子,所以也難以通過線程間的并行有效掩蓋訪問延遲.另外,對于lenet-conv1算子,cuDNN 采用implicit gemm[15]算法替換了fft,使得lenet-conv1 的執(zhí)行時間少于lenet-conv2,消除了批大小為64 時lenet-conv1 與lenet-conv2 之間的性能倒掛現(xiàn)象.此外,相對于Escoin,我們的方法在alexnet-conv1 上的收益非常顯著.由于Escoin 內(nèi)部根據(jù)數(shù)據(jù)形狀、批大小和參數(shù)的稀疏程度等信息硬編碼了一些算子到具體kernel 的映射規(guī)則,這些規(guī)則并不準(zhǔn)確,負(fù)責(zé)alexnet-conv1 的kernel 中存在大量非合并的全局內(nèi)存訪問,導(dǎo)致其性能發(fā)生了顯著降低.

    3.3 與結(jié)構(gòu)化剪枝方法的對比分析

    在這一節(jié)中,我們與基于通道剪枝和卷積核剪枝的結(jié)構(gòu)化剪枝方法進(jìn)行比較.具體來說,對每一個實(shí)驗(yàn)算子,我們考慮了刪除一半輸入通道(pruning channel,簡稱PC)、刪除一半卷積核(pruning filter,簡稱PF)以及同時刪除一半輸入通道和一半卷積核(both)這3 種情況.由于結(jié)構(gòu)化剪枝產(chǎn)生的是規(guī)模更小的稠密參數(shù),我們使用cuDNN 實(shí)現(xiàn)了上面3 種剪枝后的卷積,并與我們生成的代碼進(jìn)行了性能對比.由于PC 和PF 可以移除卷積中50%的參數(shù),我們使用了在0.5 稀疏程度下生成的優(yōu)化代碼進(jìn)行對比;對于同時刪除輸入通道和卷積核的情況(both),其稀疏程度可達(dá)0.75,我們使用0.8 稀疏程度下的代碼對比.

    圖9 展示了批大小為64 和批大小為1 時的實(shí)驗(yàn)結(jié)果.對于輸入通道數(shù)目很小且是奇數(shù)的算子(alexnetconv1,lenet-conv1,vgg-conv1),我們不對其輸入通道進(jìn)行刪除,因此PC 跳過了這些算子;同時,由于不刪除輸入通道,因此Both 和PF 在這些算子上性能一致.對于每一個算子,我們將各個方法的性能相對稠密情況下cuDNN 的性能(dense)做了歸一化,數(shù)值大于1 表示性能好于稠密情況下的cuDNN.

    相對于PF 與PC,我們生成的代碼在大部分算子上實(shí)現(xiàn)了更好的性能.

    · 在批大小為64 時,相對PC 和PF 在10 個算子上分別實(shí)現(xiàn)了平均1.3 倍和2.1 倍的加速;相對Both 實(shí)現(xiàn)了2.1 倍的加速;

    · 批大小為1 時結(jié)果類似,對PC,PF 和Both 的加速比分別為1.3 倍、2.1 倍和1.5 倍.

    我們也發(fā)現(xiàn):由于cuDNN 對內(nèi)部實(shí)現(xiàn)方法的選擇策略等原因,算子在不同剪枝情況下的性能變化與計(jì)算量不完全一致.例如:在批大小為1 時,對于alexnet-conv2,cuDNN 對PF 對應(yīng)的卷積選擇使用fft 實(shí)現(xiàn),而對PC 和Both 都使用了implicit gemm 的方法.另外,通過nvprof 我們發(fā)現(xiàn),PC 和Both 實(shí)際上執(zhí)行的單精度浮點(diǎn)操作數(shù)目十分接近.我們猜測:為了利用預(yù)先調(diào)優(yōu)的內(nèi)部kernel 實(shí)現(xiàn),cuDNN 可能對Both 的情況作了數(shù)據(jù)補(bǔ)齊,導(dǎo)致了冗余計(jì)算.對批大小為1 時的resnet-conv1 算子,cuDNN 對PC 和Both 均使用顯式的im2col 接GEMM 的方法實(shí)現(xiàn),而對PF 使用了implicit gemm 的方法,造成PC 與PF 雖然計(jì)算量類似,但PC 性能顯著差于PF;而Both 雖然計(jì)算需求僅為PF 的一半,但性能仍然不及PF.

    3.4 刪除指令數(shù)目分析

    在這一節(jié)中,我們分析冗余指令刪除對最終卷積算子性能的影響.表3 展示了在稀疏程度從0.1 逐步增加到0.9 的過程中,生成稀疏算子代碼時刪除的指令數(shù)目和算子獲得的加速效果.我們使用每個稀疏算子相對于其稠密版本的加速比衡量其性能改善.我們選取了3 個有代表性的算子.可以看到:隨著稀疏程度增加,中間表示模板中有越來越多的指令被刪除,而同時,稀疏算子代碼的性能也逐漸提升.

    Table 3 Redundant instruction number and speedups under various sparsity levels表3 不同稀疏程度下刪除的冗余指令數(shù)目和加速比

    我們又進(jìn)一步比較了在基于PTX 的中間表示中刪除的指令數(shù)目與在最終機(jī)器指令中減少的指令數(shù)目.由于PTX 中的一條FFMA 指令對應(yīng)于機(jī)器代碼中的一條乘累加機(jī)器指令,如果在稀疏情況下,減少的機(jī)器指令數(shù)目多于PTX 指令數(shù)目,說明ptxas 匯編器對生成的PTX 稀疏算子代碼進(jìn)行了額外的優(yōu)化,從中進(jìn)一步消除了其他的冗余指令,例如訪存指令等.我們發(fā)現(xiàn):在實(shí)驗(yàn)的10 個算子中,減少的機(jī)器指令數(shù)目平均為刪除的PTX 指令數(shù)的1.35~1.75 倍,證明了我們生成的PTX 稀疏算子代碼能夠支持匯編器進(jìn)行進(jìn)一步的冗余指令刪除.

    3.5 訪存優(yōu)化分析

    在這一節(jié)中,我們對稀疏卷積代碼生成方法中的訪存優(yōu)化技術(shù)的直接效果進(jìn)行評估.由于英偉達(dá)GPU 上的性能剖析工具nvprof 不支持直接測量常量內(nèi)存和常量緩存的訪問情況,我們使用兩個其他指標(biāo)間接說明優(yōu)化的效果.首先,我們測試全局內(nèi)存的平均訪問吞吐量.由于對稀疏參數(shù)的訪問不再經(jīng)過全局內(nèi)存,與位于全局內(nèi)存中的輸入數(shù)據(jù)使用了不同的訪問路徑,避免了相互之間的干擾,因此全局內(nèi)存的訪問吞吐量可以獲得提升.另外,我們也測量了DRAM 的平均訪問吞吐量,觀察同時使用全局內(nèi)存和常量內(nèi)存對DRAM 吞吐量的改進(jìn).

    我們通過與基于cuSPARSE 的卷積實(shí)現(xiàn)進(jìn)行比較,說明訪存優(yōu)化的效果.圖10 展示了實(shí)驗(yàn)結(jié)果.可以看到,生成的稀疏算子在所有的卷積中都實(shí)現(xiàn)了更好的DRAM 和全局內(nèi)存訪問吞吐量.其中,稀疏算子DRAM 吞吐量是cuSPARSE 的1.4 倍~14 倍,全局內(nèi)存訪問吞吐量是cuSPARSE 的1.1 倍~3.2 倍.

    3.6 稀疏程度對性能的影響

    這一節(jié)通過實(shí)驗(yàn)研究本文稀疏卷積代碼生成方法對不同稀疏程度的適應(yīng)性.由于同一個算子可能在同一個神經(jīng)網(wǎng)絡(luò)的不同位置以及不同神經(jīng)網(wǎng)絡(luò)中使用,因此可能對應(yīng)不同稀疏程度的模型參數(shù).為了進(jìn)一步評估在不同稀疏程度下,我們的方法將稀疏性轉(zhuǎn)化為性能收益的能力,我們隨機(jī)生成了稀疏程度從0.1~0.9 的9 種稀疏參數(shù),之后分別進(jìn)行稀疏優(yōu)化,獲得對應(yīng)不同稀疏程度的算子代碼.之后,我們計(jì)算不同稀疏程度下,每個算子對cuDNN,cuBLAS,cuSPARSE 和Escoin 的加速比.圖11 展示了實(shí)驗(yàn)結(jié)果.由于空間限制,我們僅選擇5 個算子作為代表,其他算子趨勢類似,其中,alexnet-conv2 和lenet-conv2 的計(jì)算量較小,剩余3 個算子計(jì)算量較大.

    從圖11(a)中可以看出:隨著稀疏程度的增加,我們生成的稀疏算子相對cuDNN 的性能收益越明顯.生成的稀疏算子的性能隨稀疏程度的增加逐漸提升,表明我們所提出的優(yōu)化方法有能力對不同的稀疏程度發(fā)揮作用.對于批大小為64 的情況,在0.1 的稀疏程度下,算子可以接近或超過cuDNN 的性能.在稀疏程度達(dá)到0.5 時,相對cuDNN 可以獲得至少1.5 倍的加速.如果批大小為1,稀疏程度在0.1~0.9 之間時,我們的方法相對cuDNN 可以實(shí)現(xiàn)0.7 倍~4.9 倍的性能收益.

    對于cuBLAS 也有類似的結(jié)果,批大小為64 時,在稀疏程度達(dá)到0.2 的情況下,生成的代碼的性能可以超過或與cuBLAS 持平;隨稀疏程度增加,獲得的性能收益也越明顯.在稀疏程度達(dá)到0.5 時,在全部算子上可以獲得平均10.4 倍的加速.而當(dāng)批大小為1 時,獲得的加速比在0.6 倍~3.2 倍的范圍內(nèi).另外,由于cuBLAS 在計(jì)算量不同的kernel 上的性能存在顯著差異,在alexnet-conv2 和lenet-conv2 上,我們的方法在很低的稀疏程度下就取得了明顯的性能收益.

    對于其他的稀疏計(jì)算方法,相對于cuSPARSE 和Escoin,生成的稀疏卷積算子展示出了更明顯的性能優(yōu)勢.批大小為64 時,稀疏算子在計(jì)算量較小的卷積上展示出了更好的加速效果.這一方面得益于我們的卷積模板更加高效,同時,由于這些卷積的代碼長度較短,循環(huán)展開后編譯器能夠更有效地進(jìn)行指令調(diào)度等優(yōu)化;另一方面,cuSPARSE 和Escoin 對小卷積的優(yōu)化不足.類似cuBLAS,他們在小卷積上的性能與大規(guī)模卷積的性能之間存在明顯差距.這使得在很低的稀疏程度下,我們生成的算子性能就可以顯著超過cuSPARSE 和Escoin.另外,當(dāng)稀疏程度很高時(0.8~0.9),cuSPARSE 的性能相對較低稀疏程度有所改善.但我們生成的稀疏算子仍能獲得5.5~59.5倍的加速.在所有的算子和稀疏程度下,我們的方法都能獲得相對cuSPARSE 至少5.5 倍的加速.對于批大小為1的場景,在0.1~0.9 的稀疏程度下,我們的方法對于cuSPARSE 可以獲得1.2 倍~22.9 倍的加速.

    我們的方法對Escoin 的性能優(yōu)勢也很明顯.在批大小為64 和1 時,我們的方法在所有稀疏程度和算子上平均可實(shí)現(xiàn)18.1 倍和4.1 倍的加速.我們在代碼中發(fā)現(xiàn):Escoin 中存在眾多硬編碼的固定的優(yōu)化參數(shù)(例如tile size等)以及kernel 選擇規(guī)則,這些參數(shù)與具體問題規(guī)模和平臺相關(guān),限制了Escoin 在其他平臺和算子上的性能表現(xiàn).例如:當(dāng)稀疏程度從0.8 增加到0.9 時,Escoin 將使用不同的kernel,圖11(d)中前3 個算子因此獲得了明顯的性能提升.然而這一硬編碼的規(guī)則并沒有充分考慮算子間的差異,對于vgg-conv3 和alexnet-conv1,新的kernel 則會造成性能下降的問題.在不同稀疏程度下,我們生成的代碼都展現(xiàn)了明顯的性能優(yōu)勢,證明在使用GPU 執(zhí)行稀疏卷積神經(jīng)網(wǎng)絡(luò)時,我們的方法是更好的選擇.

    3.7 開銷分析

    這一節(jié)關(guān)注開銷問題.由于本文的代碼生成方法與稀疏參數(shù)的取值緊密相關(guān),稀疏參數(shù)的取值被編碼在生成的ptx 代碼中,并經(jīng)過ptxas 匯編器編譯為二進(jìn)制cubin 文件;同時,由于循環(huán)展開,在ptx 和cubin 中的指令數(shù)目會顯著增加.這可能導(dǎo)致生成的文件體積較大,并在執(zhí)行過程中給指令的訪問帶來壓力.我們對生成文件的體積進(jìn)行分析,同時,通過profiling 分析循環(huán)展開后指令數(shù)目膨脹對運(yùn)行時的指令訪問造成的影響.

    首先,我們對各個算子在卷積參數(shù)稠密、稀疏程度為0.5 和稀疏程度為0.9 時,對應(yīng)的ptx 代碼和編譯生成的cubin 二進(jìn)制文件的體積進(jìn)行了統(tǒng)計(jì),結(jié)果展示在表4 中.

    Table 4 Sizes of ptx and cubin files in KB under various sparsity levels表4 不同稀疏程度下ptx 與cubin 文件大小,單位KB

    由于ptx 是文本形式的文件,因此其體積比cubin 更大.在0.9 的稀疏程度下,執(zhí)行的cubin 文件大小為7.29KB~709.35KB.除了存儲開銷,我們也考慮循環(huán)展開造成的指令數(shù)目膨脹對運(yùn)行時指令訪問的影響.我們繼續(xù)使用nvprof 工具,統(tǒng)計(jì)由于指令訪問延遲導(dǎo)致線程阻塞的比例.我們將我們的方法生成的kernel 與cuDNN 和cuSPARSE 進(jìn)行了對比,實(shí)驗(yàn)中,使用的稀疏程度為0.9,在10 個算子上的實(shí)驗(yàn)結(jié)果見表5.

    Table 5 Percentage of stalls caused by instruction fetch delay (%)表5 由于獲取下一條指令的延遲導(dǎo)致執(zhí)行阻塞的比例 (%)

    相對于cuDNN 和cuSPARSE,我們生成的kernel 在運(yùn)行時,由于指令訪問延遲帶來的阻塞比例更低.由于循環(huán)展開消除了部分與控制流相關(guān)的指令,使得對指令的訪問變?yōu)轫樞蛟L問的模式,GPU 上的指令訪問部件也可以更好地預(yù)測下一步將要執(zhí)行的指令,并進(jìn)行對指令的讀取.

    4 相關(guān)工作

    在這一節(jié)中,我們對相關(guān)工作進(jìn)行分析.我們主要介紹其他以加速稀疏神經(jīng)網(wǎng)絡(luò)執(zhí)行為目標(biāo)的工作.從實(shí)現(xiàn)方法區(qū)分,已有工作可以分為軟件層面的優(yōu)化方法和硬件層面的加速器設(shè)計(jì).

    4.1 稀疏神經(jīng)網(wǎng)絡(luò)性能優(yōu)化

    Intel 提出了GS[26]算法優(yōu)化CPU 上的稀疏卷積.GS 將稀疏卷積視為稀疏矩陣-稠密矩陣乘法問題,稠密矩陣基于卷積的輸入變換得到.GS 將稠密矩陣的生成集成在了計(jì)算中,以降低訪存需求,提升計(jì)算密度.另外,GS使用了tiling 和向量化等技術(shù)優(yōu)化在CPU 上的數(shù)據(jù)訪問和指令吞吐量.GS 使用CSR 存儲稀疏模型參數(shù),與本文的方法相比,會占用額外的存儲空間并導(dǎo)致更多的運(yùn)行時訪存.作者在論文中發(fā)現(xiàn),基于CSR 表示的稀疏參數(shù)會帶來約1 倍的存儲開銷.SparseCNN[30]也利用了為特定稀疏矩陣定制相應(yīng)運(yùn)算的思想,作者對模型壓縮后引入的稀疏矩陣和稠密矩陣乘法在CPU AVX256 指令集上進(jìn)行了手工實(shí)現(xiàn).作者對開源的OpenBLAS[31]進(jìn)行了修改,基于OpenBLAS 中的tiling 框架,作者去除了與無效分塊進(jìn)行計(jì)算的代碼.雖然基于類似的消除冗余計(jì)算的思想,但本文的方法基于一種通用的中間表示,不需要對同一算子的不同稀疏參數(shù)重復(fù)編寫和手工調(diào)優(yōu)代碼.SDC[32]在執(zhí)行神經(jīng)網(wǎng)絡(luò)前為稀疏參數(shù)引入了一個額外的預(yù)處理步驟,計(jì)算每個有效參數(shù)在輸入張量上對應(yīng)的偏移量.在后續(xù)進(jìn)行計(jì)算時,基于這個偏移量訪問輸入數(shù)據(jù).SDC 降低了運(yùn)行時計(jì)算每個有效參數(shù)對應(yīng)的輸入數(shù)據(jù)位置的計(jì)算量,但對每個有效參數(shù),仍然需要一個額外的偏移量記錄位置信息.本文的方法避免了位置信息的記錄,進(jìn)一步降低了計(jì)算過程中與位置信息相關(guān)的計(jì)算和訪存需求.另外,以上工作均面向CPU,本文的方法針對GPU 平臺.上述工作的優(yōu)化技術(shù)并不能直接應(yīng)用到GPU 平臺上.本文基于GPU 的特點(diǎn)設(shè)計(jì)了算子模板,并結(jié)合PTX 指令的特點(diǎn)設(shè)計(jì)了冗余指令刪除的稀疏代碼生成方法.同時利用了GPU 存儲層次和訪存路徑的特點(diǎn),優(yōu)化了稀疏卷積運(yùn)行時的訪存性能.

    Escoin[24]也針對稀疏卷積在GPU 平臺上性能差的問題,它使用GS 中的卷積算法,并對其在GPU 上的實(shí)現(xiàn)進(jìn)行了優(yōu)化.作者利用了共享內(nèi)存和高速緩存實(shí)現(xiàn)數(shù)據(jù)重用,改善訪存吞吐量.本文的方法采用了從稠密代碼中刪除冗余指令的方法,為具體的稀疏參數(shù)定制對應(yīng)的算子代碼.另外,由于采用GS 提出的稀疏卷積計(jì)算方法,Escoin 也繼承了CSR 稀疏格式占用額外位置信息的缺點(diǎn).也有一些工作從稀疏性的分布規(guī)律入手,進(jìn)行稀疏卷積在GPU 上的優(yōu)化.這些工作對稀疏數(shù)據(jù)中非零元素的分布進(jìn)行了約束和假設(shè),降低優(yōu)化稀疏計(jì)算的難度.Scott 等人在文獻(xiàn)[33]中為參數(shù)具有分塊稀疏特點(diǎn)的全連接算子和卷積算子設(shè)計(jì)了高效的GPU 實(shí)現(xiàn),并展示了基于分塊稀疏參數(shù)構(gòu)建小世界LSTM 等算法的有效性.在文獻(xiàn)[34]中,作者提出了均衡剪枝方法,將矩陣每一行分為等寬的多個塊,在剪枝時,要求所有塊內(nèi)保留相同數(shù)目的非0 元素.作者利用這一性質(zhì)實(shí)現(xiàn)了不同GPU 線程間的負(fù)載均衡,并使用共享內(nèi)存解決在輸入數(shù)據(jù)上的不連續(xù)訪存問題.與以上工作相比,我們的方法不對剪枝后稀疏模型參數(shù)的分布做任何約束,因此可以在通過任意剪枝方法獲得的模型上工作,同時也給模型剪枝算法留下了更大的空間,有助于剪枝算法刪除更多的參數(shù).

    4.2 稀疏神經(jīng)網(wǎng)絡(luò)加速器

    面對稀疏神經(jīng)網(wǎng)絡(luò)計(jì)算難以在現(xiàn)有處理器上獲得有效加速的問題,也有一些工作嘗試通過設(shè)計(jì)新的加速器進(jìn)行解決.由于稀疏模型參數(shù)數(shù)目顯著降低,且數(shù)據(jù)搬運(yùn)的能耗往往高于代數(shù)計(jì)算[11],EIE[35]將稀疏模型的參數(shù)放入片上緩存中,節(jié)約了大量的能耗.SCNN[36]同時利用參數(shù)中的稀疏性和ReLU 激活函數(shù)[1]在輸入數(shù)據(jù)中引入的稀疏性,利用笛卡爾積計(jì)算卷積.在文獻(xiàn)[37]中,作者在GPU 上增加了額外的部件,用于在運(yùn)行時跳過取值為0 的參數(shù)對應(yīng)的冗余指令.與以上工作相比,本文使用了純軟件的方法在現(xiàn)有的GPU 平臺上實(shí)現(xiàn)了稀疏卷積的加速,不需要對現(xiàn)有硬件平臺進(jìn)行修改.

    5 總結(jié)與未來工作

    在本文中,我們提出了一種加速剪枝后稀疏卷積神經(jīng)網(wǎng)絡(luò)在GPU 上執(zhí)行的優(yōu)化方法.我們基于從稠密代碼中刪除冗余指令的思想,設(shè)計(jì)實(shí)現(xiàn)了一個稀疏優(yōu)化框架.在算子模板中,我們將模板參數(shù)與計(jì)算指令綁定,并建立基于PTX 的算子中間表示模板.基于中間表示模板和具體的稀疏參數(shù)取值,通過分析識別冗余的指令,生成對應(yīng)的GPU 程序.為了改善稀疏計(jì)算的訪存瓶頸,我們利用常量緩存加速稀疏參數(shù)的訪問;同時,在生成的算子代碼中隱式編碼非0 參數(shù)的位置信息,避免了存儲位置信息帶來的額外訪存需求.通過實(shí)驗(yàn),我們驗(yàn)證了本文所提出的方法能夠有效改善稀疏卷積在GPU 上的執(zhí)行效率,并且相對已有方法實(shí)現(xiàn)了顯著的加速效果.

    未來,我們計(jì)劃從多個方面改進(jìn)當(dāng)前的工作.

    · 首先是算子模板的編譯速度.由于需要確定參數(shù)與對應(yīng)指令的關(guān)系,我們需要將模型參數(shù)涉及的計(jì)算進(jìn)行循環(huán)展開.當(dāng)算子規(guī)模比較大時,會導(dǎo)致展開后的代碼序列很長,這會影響編譯生成PTX 中間表示的速度.盡管生成的PTX 中間表示模板可以用于同一算子的不同稀疏參數(shù),但加快編譯生成PTX 的速度能幫助我們探索在更多算子上的性能情況,同時也使我們可以在算子模板上嘗試更多的優(yōu)化技術(shù).由于展開的循環(huán)序列執(zhí)行非常類似的計(jì)算,我們希望能夠利用這一特點(diǎn),在循環(huán)之間復(fù)用PTX 代碼,以改進(jìn)編譯生成PTX 中間表示的速度;

    · 第二,我們希望探索在CPU 上基于稠密中間表示模板,建立優(yōu)化稀疏程序的思路.

    猜你喜歡
    指令方法模型
    一半模型
    聽我指令:大催眠術(shù)
    重要模型『一線三等角』
    重尾非線性自回歸模型自加權(quán)M-估計(jì)的漸近分布
    ARINC661顯控指令快速驗(yàn)證方法
    LED照明產(chǎn)品歐盟ErP指令要求解讀
    電子測試(2018年18期)2018-11-14 02:30:34
    可能是方法不對
    3D打印中的模型分割與打包
    用對方法才能瘦
    Coco薇(2016年2期)2016-03-22 02:42:52
    四大方法 教你不再“坐以待病”!
    Coco薇(2015年1期)2015-08-13 02:47:34
    法律面前人人平等表现在哪些方面| 神马国产精品三级电影在线观看 | 亚洲三区欧美一区| 欧美乱码精品一区二区三区| 看黄色毛片网站| 久久久久免费精品人妻一区二区 | 18禁黄网站禁片免费观看直播| 午夜福利欧美成人| 97人妻精品一区二区三区麻豆 | 亚洲成av人片免费观看| 制服丝袜大香蕉在线| 一个人免费在线观看的高清视频| 男人舔女人的私密视频| 久久人人精品亚洲av| 一二三四在线观看免费中文在| 亚洲国产高清在线一区二区三 | 国产野战对白在线观看| 亚洲国产欧美日韩在线播放| 国产激情偷乱视频一区二区| 日韩大尺度精品在线看网址| 色综合婷婷激情| 精品久久久久久久人妻蜜臀av| 真人做人爱边吃奶动态| 亚洲自偷自拍图片 自拍| 色老头精品视频在线观看| 亚洲电影在线观看av| 波多野结衣高清无吗| 村上凉子中文字幕在线| 久久精品夜夜夜夜夜久久蜜豆 | 日韩大尺度精品在线看网址| 国产激情偷乱视频一区二区| 色综合婷婷激情| 亚洲最大成人中文| 亚洲午夜精品一区,二区,三区| 色综合婷婷激情| 国产精品乱码一区二三区的特点| 黄色成人免费大全| 亚洲精品中文字幕在线视频| 91九色精品人成在线观看| 欧美精品亚洲一区二区| 国产亚洲av高清不卡| 亚洲电影在线观看av| 12—13女人毛片做爰片一| 亚洲国产精品sss在线观看| 欧美黑人精品巨大| 久久久水蜜桃国产精品网| 91av网站免费观看| 亚洲精品久久国产高清桃花| 男人操女人黄网站| 别揉我奶头~嗯~啊~动态视频| 首页视频小说图片口味搜索| 成人亚洲精品av一区二区| 男女那种视频在线观看| 国产精品野战在线观看| 超碰成人久久| 久久精品91蜜桃| av天堂在线播放| 亚洲全国av大片| 美女免费视频网站| 亚洲精品美女久久久久99蜜臀| 中文字幕人妻丝袜一区二区| 国产精品99久久99久久久不卡| 久久久久久免费高清国产稀缺| 欧美日韩黄片免| 男女午夜视频在线观看| 两个人免费观看高清视频| 亚洲精品色激情综合| 欧美黑人欧美精品刺激| or卡值多少钱| 亚洲精华国产精华精| 欧美人与性动交α欧美精品济南到| 久久久精品国产亚洲av高清涩受| 午夜久久久在线观看| 脱女人内裤的视频| 激情在线观看视频在线高清| 免费无遮挡裸体视频| 男人舔女人的私密视频| 在线视频色国产色| 免费高清视频大片| 久久中文看片网| 婷婷丁香在线五月| 日本三级黄在线观看| 精品国内亚洲2022精品成人| 午夜免费鲁丝| 丝袜美腿诱惑在线| 嫩草影院精品99| 午夜免费激情av| 亚洲成国产人片在线观看| 免费观看精品视频网站| 欧美乱码精品一区二区三区| 国产精品免费视频内射| 99国产极品粉嫩在线观看| 精品乱码久久久久久99久播| 99国产综合亚洲精品| 麻豆av在线久日| 两人在一起打扑克的视频| 黄色丝袜av网址大全| 精品高清国产在线一区| www日本在线高清视频| 欧美亚洲日本最大视频资源| 91麻豆av在线| www国产在线视频色| 黄色a级毛片大全视频| 韩国av一区二区三区四区| 久久香蕉精品热| 国产亚洲精品第一综合不卡| 18禁国产床啪视频网站| 午夜福利免费观看在线| 久久精品91无色码中文字幕| 日本撒尿小便嘘嘘汇集6| 最近最新中文字幕大全电影3 | 国产免费男女视频| 999久久久精品免费观看国产| 村上凉子中文字幕在线| 深夜精品福利| 欧美性猛交╳xxx乱大交人| 又大又爽又粗| 亚洲成国产人片在线观看| 久久青草综合色| 777久久人妻少妇嫩草av网站| 久久久久久人人人人人| 久久精品国产亚洲av香蕉五月| 欧美日韩中文字幕国产精品一区二区三区| 免费看十八禁软件| 亚洲一区高清亚洲精品| 日日夜夜操网爽| 女同久久另类99精品国产91| 亚洲精品在线观看二区| 99精品欧美一区二区三区四区| 一夜夜www| 99在线视频只有这里精品首页| 欧美国产日韩亚洲一区| 在线十欧美十亚洲十日本专区| 此物有八面人人有两片| 99热只有精品国产| 男女视频在线观看网站免费 | 久久久久久亚洲精品国产蜜桃av| 欧美大码av| 欧美精品亚洲一区二区| 亚洲国产精品sss在线观看| 久久久久久大精品| 91国产中文字幕| 国产v大片淫在线免费观看| 欧美成人免费av一区二区三区| 精品国产乱子伦一区二区三区| 欧美精品亚洲一区二区| 一区二区三区高清视频在线| 丁香欧美五月| 一个人免费在线观看的高清视频| 日韩大码丰满熟妇| 人妻久久中文字幕网| 搡老熟女国产l中国老女人| 自线自在国产av| 亚洲久久久国产精品| 日日干狠狠操夜夜爽| 国产97色在线日韩免费| 丁香六月欧美| 动漫黄色视频在线观看| 他把我摸到了高潮在线观看| 色播亚洲综合网| 午夜福利成人在线免费观看| 一本综合久久免费| 伊人久久大香线蕉亚洲五| 国产91精品成人一区二区三区| 国内毛片毛片毛片毛片毛片| 日韩有码中文字幕| 最近最新中文字幕大全电影3 | 最好的美女福利视频网| 99热只有精品国产| 欧美黑人巨大hd| 国产精品亚洲av一区麻豆| 国产亚洲精品av在线| 成人av一区二区三区在线看| 天天躁狠狠躁夜夜躁狠狠躁| www.999成人在线观看| 免费搜索国产男女视频| 在线av久久热| 精品久久久久久久人妻蜜臀av| 男人舔女人的私密视频| 国产一区二区激情短视频| 午夜精品久久久久久毛片777| 日本一本二区三区精品| 美女国产高潮福利片在线看| 久久人人精品亚洲av| 天天添夜夜摸| 无人区码免费观看不卡| 可以在线观看毛片的网站| 亚洲国产高清在线一区二区三 | 最好的美女福利视频网| 久久久久久国产a免费观看| 高清毛片免费观看视频网站| 久久伊人香网站| 99国产精品一区二区三区| 亚洲国产毛片av蜜桃av| 美女高潮喷水抽搐中文字幕| 丝袜人妻中文字幕| 日韩欧美在线二视频| 免费在线观看视频国产中文字幕亚洲| 老汉色∧v一级毛片| 欧美一区二区精品小视频在线| 久久亚洲精品不卡| 午夜亚洲福利在线播放| 亚洲精华国产精华精| 国产极品粉嫩免费观看在线| 亚洲一区高清亚洲精品| 午夜久久久久精精品| 午夜激情av网站| 久久精品夜夜夜夜夜久久蜜豆 | 岛国视频午夜一区免费看| 日韩高清综合在线| 日本三级黄在线观看| 白带黄色成豆腐渣| 久久狼人影院| 午夜两性在线视频| 国产三级在线视频| 琪琪午夜伦伦电影理论片6080| 99精品久久久久人妻精品| 日日摸夜夜添夜夜添小说| 每晚都被弄得嗷嗷叫到高潮| 国产亚洲欧美在线一区二区| 国产真实乱freesex| 色综合婷婷激情| 一级a爱片免费观看的视频| 亚洲黑人精品在线| 级片在线观看| 老汉色∧v一级毛片| 欧美日韩中文字幕国产精品一区二区三区| av福利片在线| 一区二区三区国产精品乱码| 亚洲精品在线观看二区| 欧美日韩乱码在线| 久久精品国产99精品国产亚洲性色| av电影中文网址| 波多野结衣av一区二区av| 女生性感内裤真人,穿戴方法视频| 精品熟女少妇八av免费久了| 亚洲精品av麻豆狂野| 亚洲精品在线观看二区| 制服丝袜大香蕉在线| 十分钟在线观看高清视频www| 亚洲va日本ⅴa欧美va伊人久久| 午夜a级毛片| 男女视频在线观看网站免费 | 久久国产亚洲av麻豆专区| 精品电影一区二区在线| 波多野结衣高清作品| 一级作爱视频免费观看| 真人做人爱边吃奶动态| 欧美+亚洲+日韩+国产| 成在线人永久免费视频| 国产精品亚洲av一区麻豆| 又黄又爽又免费观看的视频| 午夜免费成人在线视频| 亚洲av电影在线进入| 国产精品久久久久久人妻精品电影| 久久久国产成人精品二区| 又黄又粗又硬又大视频| 18禁黄网站禁片免费观看直播| 久久久久久久精品吃奶| 人妻久久中文字幕网| 激情在线观看视频在线高清| 亚洲片人在线观看| 日韩av在线大香蕉| 午夜久久久在线观看| 黑人巨大精品欧美一区二区mp4| 免费电影在线观看免费观看| 国产亚洲av嫩草精品影院| 男女那种视频在线观看| 国产成人欧美| 国产黄a三级三级三级人| 麻豆国产av国片精品| 一级毛片精品| 12—13女人毛片做爰片一| 欧美日韩中文字幕国产精品一区二区三区| 黄色片一级片一级黄色片| 美国免费a级毛片| 美女免费视频网站| 麻豆av在线久日| 黄色a级毛片大全视频| 国产精品综合久久久久久久免费| 90打野战视频偷拍视频| 在线av久久热| 国产精品98久久久久久宅男小说| 亚洲久久久国产精品| 99热6这里只有精品| 日本熟妇午夜| 日韩 欧美 亚洲 中文字幕| 啪啪无遮挡十八禁网站| xxx96com| 欧美一区二区精品小视频在线| 日韩视频一区二区在线观看| 老司机福利观看| 一级黄色大片毛片| 老汉色av国产亚洲站长工具| 日韩有码中文字幕| 又黄又粗又硬又大视频| 婷婷六月久久综合丁香| 久久久久九九精品影院| 国产激情欧美一区二区| 久久久国产欧美日韩av| 色播亚洲综合网| 欧美久久黑人一区二区| 亚洲中文字幕一区二区三区有码在线看 | 国产精品免费一区二区三区在线| 又大又爽又粗| 91老司机精品| 男女午夜视频在线观看| 国产精品九九99| 成人午夜高清在线视频 | 亚洲真实伦在线观看| 亚洲黑人精品在线| 男女那种视频在线观看| 亚洲 国产 在线| 亚洲九九香蕉| www.精华液| 身体一侧抽搐| 久久久精品欧美日韩精品| 精品欧美一区二区三区在线| 欧美成人午夜精品| 免费高清视频大片| 中出人妻视频一区二区| 日韩中文字幕欧美一区二区| 国产欧美日韩精品亚洲av| bbb黄色大片| 亚洲最大成人中文| 男女做爰动态图高潮gif福利片| 桃红色精品国产亚洲av| 中文字幕高清在线视频| 精品久久久久久,| 日韩大码丰满熟妇| 黑人操中国人逼视频| 国产高清激情床上av| 日韩一卡2卡3卡4卡2021年| 岛国在线观看网站| 亚洲国产欧洲综合997久久, | 嫩草影视91久久| 午夜亚洲福利在线播放| 最近最新中文字幕大全电影3 | 香蕉丝袜av| 91大片在线观看| 免费在线观看视频国产中文字幕亚洲| 97人妻精品一区二区三区麻豆 | 一二三四在线观看免费中文在| 国产av一区二区精品久久| 欧美色视频一区免费| 好看av亚洲va欧美ⅴa在| 久久99热这里只有精品18| 国产国语露脸激情在线看| 老熟妇乱子伦视频在线观看| 在线天堂中文资源库| 亚洲av电影不卡..在线观看| 丝袜在线中文字幕| 满18在线观看网站| 啦啦啦观看免费观看视频高清| 成人三级黄色视频| 在线观看午夜福利视频| 亚洲天堂国产精品一区在线| 国产三级在线视频| 中亚洲国语对白在线视频| 国产成人精品久久二区二区免费| 男女下面进入的视频免费午夜 | 国产1区2区3区精品| 男女下面进入的视频免费午夜 | 99久久99久久久精品蜜桃| 男人舔女人下体高潮全视频| 可以在线观看的亚洲视频| 欧美国产精品va在线观看不卡| 国产成年人精品一区二区| 成年免费大片在线观看| 亚洲av五月六月丁香网| 19禁男女啪啪无遮挡网站| 亚洲第一欧美日韩一区二区三区| 亚洲精品在线美女| 国产亚洲精品久久久久5区| 最新美女视频免费是黄的| 午夜福利在线在线| 久久久久久国产a免费观看| 午夜成年电影在线免费观看| 色哟哟哟哟哟哟| 一夜夜www| 啦啦啦韩国在线观看视频| 美女午夜性视频免费| 国产熟女午夜一区二区三区| 在线十欧美十亚洲十日本专区| 免费电影在线观看免费观看| 在线看三级毛片| 国产精品99久久99久久久不卡| 十八禁网站免费在线| 人妻久久中文字幕网| 国内少妇人妻偷人精品xxx网站 | 不卡av一区二区三区| 国产成年人精品一区二区| 成人国语在线视频| 精品一区二区三区视频在线观看免费| 国产精品爽爽va在线观看网站 | 亚洲中文字幕日韩| 免费看美女性在线毛片视频| 一本精品99久久精品77| 精品久久久久久,| 亚洲一卡2卡3卡4卡5卡精品中文| 不卡av一区二区三区| 琪琪午夜伦伦电影理论片6080| 久久午夜综合久久蜜桃| 人人妻,人人澡人人爽秒播| 亚洲五月天丁香| 亚洲一区二区三区不卡视频| 黄片小视频在线播放| 两人在一起打扑克的视频| 99久久久亚洲精品蜜臀av| 18美女黄网站色大片免费观看| 91九色精品人成在线观看| 在线永久观看黄色视频| 18美女黄网站色大片免费观看| 看黄色毛片网站| 少妇被粗大的猛进出69影院| 欧美乱妇无乱码| 美女国产高潮福利片在线看| 久久久国产精品麻豆| 日本一本二区三区精品| 最好的美女福利视频网| 99在线视频只有这里精品首页| 少妇熟女aⅴ在线视频| 亚洲av日韩精品久久久久久密| 国产人伦9x9x在线观看| 午夜福利在线在线| www.999成人在线观看| 成年免费大片在线观看| 亚洲国产高清在线一区二区三 | 亚洲 欧美 日韩 在线 免费| 美女大奶头视频| 国产精品美女特级片免费视频播放器 | 国产亚洲精品一区二区www| 两个人免费观看高清视频| 非洲黑人性xxxx精品又粗又长| 亚洲中文字幕日韩| 免费看美女性在线毛片视频| 伦理电影免费视频| 欧美黑人精品巨大| 国产97色在线日韩免费| 丝袜在线中文字幕| 国产成人影院久久av| 亚洲国产精品合色在线| 90打野战视频偷拍视频| 欧美最黄视频在线播放免费| 久久中文看片网| 成人18禁在线播放| 国产精品久久久av美女十八| 国产视频内射| 天天躁夜夜躁狠狠躁躁| 久久九九热精品免费| 麻豆成人av在线观看| 啪啪无遮挡十八禁网站| 欧美 亚洲 国产 日韩一| 亚洲无线在线观看| 亚洲精品av麻豆狂野| 国产欧美日韩精品亚洲av| 两个人看的免费小视频| 久久精品国产亚洲av香蕉五月| 久久精品国产99精品国产亚洲性色| 自线自在国产av| 日本一区二区免费在线视频| 亚洲欧美精品综合一区二区三区| 亚洲欧美一区二区三区黑人| 午夜免费鲁丝| 午夜免费观看网址| 日韩欧美在线二视频| 男人舔女人下体高潮全视频| 久久久久国产一级毛片高清牌| 精品久久久久久,| 99热6这里只有精品| 一区二区三区高清视频在线| 欧美成狂野欧美在线观看| 麻豆成人av在线观看| 免费看十八禁软件| 手机成人av网站| 国产精品久久久久久人妻精品电影| 一级毛片精品| 99在线人妻在线中文字幕| 高潮久久久久久久久久久不卡| 国产在线观看jvid| x7x7x7水蜜桃| 午夜视频精品福利| 免费看十八禁软件| 欧美精品啪啪一区二区三区| 听说在线观看完整版免费高清| 中文字幕最新亚洲高清| 99久久久亚洲精品蜜臀av| 黄片大片在线免费观看| 久久香蕉精品热| 亚洲精品久久国产高清桃花| 久久国产精品影院| 国产成人精品无人区| 国产精品亚洲美女久久久| 性色av乱码一区二区三区2| 亚洲va日本ⅴa欧美va伊人久久| 亚洲第一青青草原| 精品一区二区三区四区五区乱码| 亚洲全国av大片| 国产亚洲av嫩草精品影院| 婷婷精品国产亚洲av| 欧美性猛交╳xxx乱大交人| 亚洲av中文字字幕乱码综合 | 国产精品美女特级片免费视频播放器 | 女性生殖器流出的白浆| 成人欧美大片| 亚洲精品美女久久久久99蜜臀| 国产片内射在线| 在线免费观看的www视频| 欧美中文综合在线视频| 男女做爰动态图高潮gif福利片| 老司机福利观看| avwww免费| 老司机福利观看| 男女下面进入的视频免费午夜 | 久热爱精品视频在线9| 午夜福利在线观看吧| 色老头精品视频在线观看| 夜夜爽天天搞| 欧美不卡视频在线免费观看 | 国产色视频综合| 美女国产高潮福利片在线看| 制服丝袜大香蕉在线| 欧美乱码精品一区二区三区| 精品久久久久久久毛片微露脸| 99精品久久久久人妻精品| 亚洲精品一卡2卡三卡4卡5卡| 亚洲aⅴ乱码一区二区在线播放 | 欧美国产精品va在线观看不卡| 免费观看人在逋| 搞女人的毛片| 丰满的人妻完整版| 久久午夜综合久久蜜桃| 人人妻人人澡欧美一区二区| 亚洲精华国产精华精| 欧美日韩精品网址| 亚洲精华国产精华精| 亚洲成人免费电影在线观看| 桃红色精品国产亚洲av| 妹子高潮喷水视频| 欧美成狂野欧美在线观看| 亚洲精品中文字幕在线视频| 欧美成狂野欧美在线观看| 亚洲中文字幕一区二区三区有码在线看 | 热99re8久久精品国产| 久久久久久免费高清国产稀缺| 色精品久久人妻99蜜桃| 777久久人妻少妇嫩草av网站| 18美女黄网站色大片免费观看| 久热爱精品视频在线9| 又大又爽又粗| 国产精品99久久99久久久不卡| 国产精品 国内视频| 一二三四在线观看免费中文在| av超薄肉色丝袜交足视频| 精品少妇一区二区三区视频日本电影| 午夜亚洲福利在线播放| 一本综合久久免费| 亚洲七黄色美女视频| 搡老熟女国产l中国老女人| 国产高清有码在线观看视频 | 久久草成人影院| 亚洲成人精品中文字幕电影| 成年免费大片在线观看| 国产精品久久久av美女十八| 特大巨黑吊av在线直播 | 欧美日韩福利视频一区二区| 国产午夜福利久久久久久| 精品熟女少妇八av免费久了| 亚洲三区欧美一区| 麻豆国产av国片精品| 午夜视频精品福利| 99久久精品国产亚洲精品| 村上凉子中文字幕在线| 午夜福利成人在线免费观看| 他把我摸到了高潮在线观看| 50天的宝宝边吃奶边哭怎么回事| 欧美黑人欧美精品刺激| 丁香六月欧美| 嫩草影院精品99| 好看av亚洲va欧美ⅴa在| 叶爱在线成人免费视频播放| 久久久久免费精品人妻一区二区 | 好男人在线观看高清免费视频 | 在线观看免费日韩欧美大片| 99久久久亚洲精品蜜臀av| 中文字幕人妻熟女乱码| 午夜免费成人在线视频| 很黄的视频免费| 精品国产一区二区三区四区第35| 欧美丝袜亚洲另类 | 中文字幕另类日韩欧美亚洲嫩草| 久久久久久久久免费视频了| 亚洲久久久国产精品| 免费观看精品视频网站| 美女高潮到喷水免费观看| 精品国产国语对白av| 日日干狠狠操夜夜爽| 婷婷精品国产亚洲av| 男人操女人黄网站| 999久久久精品免费观看国产| 国产欧美日韩一区二区精品| 欧美又色又爽又黄视频| www国产在线视频色| 亚洲激情在线av| 久久人妻av系列| 成人免费观看视频高清| 亚洲一区二区三区不卡视频| 夜夜爽天天搞| 亚洲人成网站在线播放欧美日韩| tocl精华| 999久久久精品免费观看国产| 99热6这里只有精品| 欧美av亚洲av综合av国产av| 色尼玛亚洲综合影院| 国产一区二区在线av高清观看|