日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

《CUDA C编程权威指南》——3.4 避免分支分化

發(fā)布時(shí)間:2025/7/14 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《CUDA C编程权威指南》——3.4 避免分支分化 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本節(jié)書摘來(lái)自華章計(jì)算機(jī)《CUDA C編程權(quán)威指南》一書中的第3章,第3.4節(jié),作者 [美] 馬克斯·格羅斯曼(Max Grossman),譯 顏成鋼 殷建 李亮,更多章節(jié)內(nèi)容可以訪問(wèn)云棲社區(qū)“華章計(jì)算機(jī)”公眾號(hào)查看。

3.4 避免分支分化

有時(shí),控制流依賴于線程索引。線程束中的條件執(zhí)行可能引起線程束分化,這會(huì)導(dǎo)致內(nèi)核性能變差。通過(guò)重新組織數(shù)據(jù)的獲取模式,可以減少或避免線程束分化。在本節(jié)里,將會(huì)以并行歸約為例,介紹避免分支分化的基本技術(shù)。

3.4.1 并行歸約問(wèn)題

假設(shè)要對(duì)一個(gè)有N個(gè)元素的整數(shù)數(shù)組求和。使用如下的串行代碼很容易實(shí)現(xiàn)算法:

如果有大量的數(shù)據(jù)元素會(huì)怎么樣呢?如何通過(guò)并行計(jì)算快速求和呢?鑒于加法的結(jié)合律和交換律,數(shù)組元素可以以任何順序求和。所以可以用以下的方法執(zhí)行并行加法運(yùn)算:

  • 將輸入向量劃分到更小的數(shù)據(jù)塊中。
  • 用一個(gè)線程計(jì)算一個(gè)數(shù)據(jù)塊的部分和。
  • 對(duì)每個(gè)數(shù)據(jù)塊的部分和再求和得出最終結(jié)果。
  • 并行加法的一個(gè)常用方法是使用迭代成對(duì)實(shí)現(xiàn)。一個(gè)數(shù)據(jù)塊只包含一對(duì)元素,并且一個(gè)線程對(duì)這兩個(gè)元素求和產(chǎn)生一個(gè)局部結(jié)果。然后,這些局部結(jié)果在最初的輸入向量中就地保存。這些新值被作為下一次迭代求和的輸入值。因?yàn)檩斎胫档臄?shù)量在每一次迭代后會(huì)減半,當(dāng)輸出向量的長(zhǎng)度達(dá)到1時(shí),最終的和就已經(jīng)被計(jì)算出來(lái)了。

    根據(jù)每次迭代后輸出元素就地存儲(chǔ)的位置,成對(duì)的并行求和實(shí)現(xiàn)可以被進(jìn)一步分為以下兩種類型:

    • 相鄰配對(duì):元素與它們直接相鄰的元素配對(duì)
    • 交錯(cuò)配對(duì):根據(jù)給定的跨度配對(duì)元素

    圖3-19所示為相鄰配對(duì)的實(shí)現(xiàn)。在每一步實(shí)現(xiàn)中,一個(gè)線程對(duì)兩個(gè)相鄰元素進(jìn)行操作,產(chǎn)生部分和。對(duì)于有N個(gè)元素的數(shù)組,這種實(shí)現(xiàn)方式需要N―1次求和,進(jìn)行l(wèi)og2 N步。

    圖3-20所示為交錯(cuò)配對(duì)的實(shí)現(xiàn)。值得注意的是,在這種實(shí)現(xiàn)方法的每一步中,一個(gè)線程的輸入是輸入數(shù)組長(zhǎng)度的一半。

    下列的C語(yǔ)言函數(shù)是一個(gè)交錯(cuò)配對(duì)方法的遞歸實(shí)現(xiàn):



    盡管以上代碼實(shí)現(xiàn)的是加法,但任何滿足交換律和結(jié)合律的運(yùn)算都可以代替加法。例如,通過(guò)調(diào)用max代替求和運(yùn)算,就可以計(jì)算輸入向量中的最大值。其他有效運(yùn)算的例子有最小值、平均值和乘積。

    在向量中執(zhí)行滿足交換律和結(jié)合律的運(yùn)算,被稱為歸約問(wèn)題。并行歸約問(wèn)題是這種運(yùn)算的并行執(zhí)行。并行歸約是一種最常見(jiàn)的并行模式,并且是許多并行算法中的一個(gè)關(guān)鍵運(yùn)算。

    在本節(jié)里,會(huì)實(shí)現(xiàn)多個(gè)不同的并行歸約核函數(shù),并且將測(cè)試不同的實(shí)現(xiàn)是如何影響內(nèi)核性能的。

    3.4.2 并行歸約中的分化

    圖3-21所示的是相鄰配對(duì)方法的內(nèi)核實(shí)現(xiàn)流程。每個(gè)線程將相鄰的兩個(gè)元素相加產(chǎn)生部分和。

    在這個(gè)內(nèi)核里,有兩個(gè)全局內(nèi)存數(shù)組:一個(gè)大數(shù)組用來(lái)存放整個(gè)數(shù)組,進(jìn)行歸約;另一個(gè)小數(shù)組用來(lái)存放每個(gè)線程塊的部分和。每個(gè)線程塊在數(shù)組的一部分上獨(dú)立地執(zhí)行操作。循環(huán)中迭代一次執(zhí)行一個(gè)歸約步驟。歸約是在就地完成的,這意味著在每一步,全局內(nèi)存里的值都被部分和替代。__syncthreads語(yǔ)句可以保證,線程塊中的任一線程在進(jìn)入下一次迭代之前,在當(dāng)前迭代里每個(gè)線程的所有部分和都被保存在了全局內(nèi)存中。進(jìn)入下一次迭代的所有線程都使用上一步產(chǎn)生的數(shù)值。在最后一個(gè)循環(huán)以后,整個(gè)線程塊的和被保存進(jìn)全局內(nèi)存中。


    兩個(gè)相鄰元素間的距離被稱為跨度,初始化均為1。在每一次歸約循環(huán)結(jié)束后,這個(gè)間隔就被乘以2。在第一次循環(huán)結(jié)束后,idata(全局?jǐn)?shù)據(jù)指針)的偶數(shù)元素將會(huì)被部分和替代。在第二次循環(huán)結(jié)束后,idata的每四個(gè)元素將會(huì)被新產(chǎn)生的部分和替代。因?yàn)榫€程塊間無(wú)法同步,所以每個(gè)線程塊產(chǎn)生的部分和被復(fù)制回了主機(jī),并且在那兒進(jìn)行串行求和,如圖3-22所示。

    從Wrox.com上可以找到reduceInteger.cu完整的源代碼。代碼清單3-3只列出了主函數(shù)。





    初始化輸入數(shù)組,使其包含16M元素:

    然后,內(nèi)核被配置為一維網(wǎng)格和一維塊:

    用以下的命令編譯文件:

    運(yùn)行可執(zhí)行文件,以下是運(yùn)行結(jié)果。

    在接下來(lái)的一節(jié)中,這些結(jié)果將會(huì)被作為性能調(diào)節(jié)的基準(zhǔn)。

    3.4.3 改善并行歸約的分化


    注意內(nèi)核中的下述語(yǔ)句,它為每個(gè)線程設(shè)置數(shù)組訪問(wèn)索引:

    因?yàn)榭缍瘸艘粤?,所以下面的語(yǔ)句使用線程塊的前半部分來(lái)執(zhí)行求和操作:

    對(duì)于一個(gè)有512個(gè)線程的塊來(lái)說(shuō),前8個(gè)線程束執(zhí)行第一輪歸約,剩下8個(gè)線程束什么也不做。在第二輪里,前4個(gè)線程束執(zhí)行歸約,剩下12個(gè)線程束什么也不做。因此,這樣就徹底不存在分化了。在最后五輪中,當(dāng)每一輪的線程總數(shù)小于線程束的大小時(shí),分化就會(huì)出現(xiàn)。在下一節(jié)將會(huì)介紹如何處理這一問(wèn)題。

    在主函數(shù)里調(diào)用基準(zhǔn)內(nèi)核之后,通過(guò)以下代碼段可以調(diào)用這個(gè)新內(nèi)核。

    用reduceNeighboredLess函數(shù)測(cè)試,較早的核函數(shù)將產(chǎn)生如下報(bào)告:

    新的實(shí)現(xiàn)比原來(lái)的快了1.26倍。

    可以通過(guò)測(cè)試不同的指標(biāo)來(lái)解釋這兩個(gè)內(nèi)核之間的不同行為。用inst_per_warp指標(biāo)來(lái)查看每個(gè)線程束上執(zhí)行指令數(shù)量的平均值。

    結(jié)果總結(jié)如下,原來(lái)的內(nèi)核在每個(gè)線程束里執(zhí)行的指令數(shù)是新內(nèi)核的兩倍多,它是原來(lái)實(shí)現(xiàn)高分化的一個(gè)指示器:

    用gld_throughput指標(biāo)來(lái)查看內(nèi)存加載吞吐量:

    結(jié)果總結(jié)如下,新的實(shí)現(xiàn)擁有更高的加載吞吐量,因?yàn)殡m然I/O操作數(shù)量相同,但是其耗時(shí)更短:

    3.4.4 交錯(cuò)配對(duì)的歸約

    與相鄰配對(duì)方法相比,交錯(cuò)配對(duì)方法顛倒了元素的跨度。初始跨度是線程塊大小的一半,然后在每次迭代中減少一半(如圖3-24所示)。在每次循環(huán)中,每個(gè)線程對(duì)兩個(gè)被當(dāng)前跨度隔開(kāi)的元素進(jìn)行求和,以產(chǎn)生一個(gè)部分和。與圖3-23相比,交錯(cuò)歸約的工作線程沒(méi)有變化。但是,每個(gè)線程在全局內(nèi)存中的加載/存儲(chǔ)位置是不同的。



    交錯(cuò)歸約的內(nèi)核代碼如下所示:


    注意核函數(shù)中的下述語(yǔ)句,兩個(gè)元素間的跨度被初始化為線程塊大小的一半,然后在每次循環(huán)中減少一半:

    下面的語(yǔ)句在第一次迭代時(shí)強(qiáng)制線程塊中的前半部分線程執(zhí)行求和操作,第二次迭代時(shí)是線程塊的前四分之一,以此類推:

    下面的代碼增加到主函數(shù)中,執(zhí)行交錯(cuò)歸約的代碼:

    用reduceInterleaved函數(shù)進(jìn)行測(cè)試,較早的內(nèi)核函數(shù)將產(chǎn)生如下報(bào)告:

    交錯(cuò)實(shí)現(xiàn)比第一個(gè)實(shí)現(xiàn)快了1.69倍,比第二個(gè)實(shí)現(xiàn)快了1.34倍。這種性能的提升主要是由reduceInterleaved函數(shù)里的全局內(nèi)存加載/存儲(chǔ)模式導(dǎo)致的。在第4章里會(huì)介紹更多有關(guān)于全局內(nèi)存加載/存儲(chǔ)模式對(duì)內(nèi)核性能的影響。reduceInterleaved函數(shù)和reduceNeigh-boredLess函數(shù)維持相同的線程束分化。

    總結(jié)

    以上是生活随笔為你收集整理的《CUDA C编程权威指南》——3.4 避免分支分化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。