在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何在CUDA C/C++中實現(xiàn)數(shù)據(jù)傳輸和其他操作的重疊

星星科技指導員 ? 來源:NVIDIA ? 作者:Mark Harris ? 2022-04-11 10:37 ? 次閱讀

在上一期的 C / C ++ 文章 中,我們討論了如何在主機和設備之間高效地傳輸數(shù)據(jù)。在這篇文章中,我們討論了如何將數(shù)據(jù)傳輸與主機上的計算、設備上的計算相重疊,在某些情況下,主機和設備之間的其他數(shù)據(jù)傳輸。實現(xiàn)數(shù)據(jù)傳輸和其他操作之間的重疊需要使用 CUDA 流,所以首先讓我們了解一下流。

CUDA 流

CUDA 中的 stream 是按照主機代碼發(fā)出的順序在設備上執(zhí)行的操作序列。雖然流中的操作被保證按規(guī)定的順序執(zhí)行,但是不同流中的操作可以被交錯,并且在可能的情況下,它們甚至可以并發(fā)運行。

默認流

CUDA 中的所有設備操作(內核和數(shù)據(jù)傳輸)都在一個流中運行。如果沒有指定流,則使用默認流(也稱為“空流”)。默認流與其他流不同,因為它是關于設備上操作的同步流:在所有先前發(fā)出的操作 在設備上的任何流中 完成之前,默認流中的任何操作都不會開始,并且默認流中的操作必須在任何其他操作(在設備上的任何流中)之前完成就要開始了。

請注意, 2015 年發(fā)布的 CUDA 7 引入了一個新的選項,即每個主機線程使用單獨的默認流,并將每個線程的默認流視為常規(guī)流(即它們不與其他流中的操作同步)。在文章 GPU 專業(yè)提示: CUDA 7 流簡化并發(fā) 中閱讀更多關于這種新行為的信息

讓我們看一些使用默認流的簡單代碼示例,并從主機和設備的角度討論操作是如何進行的。

cudaMemcpy(d_a, a, numBytes, cudaMemcpyHostToDevice);
increment<<<1,N>>>(d_a)
cudaMemcpy(a, d_a, numBytes, cudaMemcpyDeviceToHost);

在上面的代碼中,從設備的角度來看,所有三個操作都被發(fā)布到同一個(默認)流中,并將按照它們發(fā)出的順序執(zhí)行。

從主機的角度看,隱式數(shù)據(jù)傳輸是阻塞或同步傳輸,而內核啟動是異步的。由于第一行上的主機到設備的數(shù)據(jù)傳輸是同步的, CPU 線程在主機到設備的傳輸完成之前不會到達第二行的內核調用。一旦內核被發(fā)出, CPU 線程將移動到第三行,但由于設備端的執(zhí)行順序,該行上的傳輸無法開始。

內核從主機的角度啟動的異步行為使得重疊的設備和主機計算非常簡單。我們可以修改代碼以添加一些獨立的 CPU 計算,如下所示。

cudaMemcpy(d_a, a, numBytes, cudaMemcpyHostToDevice);
increment<<<1,N>>>(d_a)
myCpuFunction(b)
cudaMemcpy(a, d_a, numBytes, cudaMemcpyDeviceToHost);

在上面的代碼中,一旦 increment() 內核在設備上啟動, CPU 線程就執(zhí)行 myCpuFunction() ,它在 CPU 上的執(zhí)行與在 GPU 上的內核執(zhí)行重疊。無論是主機功能還是設備內核先完成,都不會影響后續(xù)的設備到主機的傳輸,只有在內核完成后才會開始,從設備的角度來看,上一個例子沒有什么變化,設備完全不知道 myCpuFunction() 。

非默認流

在下面的代碼中, CUDA C / C ++的非默認流被聲明、創(chuàng)建和銷毀。

cudaStream_t stream1;
cudaError_t result;
result = cudaStreamCreate(&stream1)
result = cudaStreamDestroy(stream1)

為了向非默認流發(fā)出數(shù)據(jù)傳輸,我們使用了cudaMemcpyAsync()函數(shù),它類似于前一篇文章中討論的cudaMemcpy()函數(shù),但將流標識符作為第五個參數(shù)

result = cudaMemcpyAsync(d_a, a, N, cudaMemcpyHostToDevice, stream1)

cudaMemcpyAsync() 在主機上是非阻塞的,因此在發(fā)出傳輸之后,控制權立即返回到主機線程。此例程有 cudaMemcpy2DAsync() 和 cudaMemcpy3DAsync() 變體,它們可以在指定的流中異步傳輸 2D 和 3D 數(shù)組部分。

為了向非默認流發(fā)出內核,我們將流標識符指定為第四個執(zhí)行配置參數(shù)(第三個執(zhí)行配置參數(shù)分配共享設備內存,我們將在后面討論;現(xiàn)在使用 0 )。

increment<<<1,N,0,stream1>>>(d_a)

與流同步

由于非默認流中的所有操作相對于宿主代碼都是非阻塞的,因此您將遇到需要將宿主代碼與流中的操作同步的情況。“重錘”的方法是使用 cudaDeviceSynchronize() ,它會阻止主機代碼,直到之前在設備上發(fā)出的所有操作都完成為止。在大多數(shù)情況下,這是一種過度殺戮,并且會由于整個設備和主機線程的暫停而影響性能。

CUDA 流 API 有多種不太嚴格的同步主機與流的方法。函數(shù) cudaStreamSynchronize(stream) 可用于阻止主機線程,直到指定流中以前發(fā)出的所有操作都已完成。函數(shù) cudaStreamQuery(stream) 測試向指定流發(fā)出的所有操作是否已完成,而不阻止主機執(zhí)行。函數(shù) cudaEventSynchronize(event) 和 cudaEventQuery(event) 的行為與它們的流對應項相似,只是它們的結果基于是否記錄了指定的事件,而不是基于指定的流是否空閑。您還可以使用 cudaStreamWaitEvent ( event )在單個流中同步特定事件的操作(即使事件記錄在不同的流中,或者記錄在不同的設備上)。

重疊的內核執(zhí)行和數(shù)據(jù)傳輸

前面我們演示了如何將默認流中的內核執(zhí)行與主機上的代碼執(zhí)行重疊。但我們在這篇文章中的主要目標是向您展示如何將內核執(zhí)行與數(shù)據(jù)傳輸重疊。要做到這一點有幾個要求。

設備必須能夠“并發(fā)復制和執(zhí)行”。這可以從 cudaDeviceProp 結構的 deviceOverlap 字段或從 CUDA SDK / Toolkit 附帶的 deviceQuery 示例的輸出中進行查詢。幾乎所有具有計算能力 1 。 1 及更高版本的設備都具有此功能。

要重疊的內核執(zhí)行和數(shù)據(jù)傳輸必須同時發(fā)生在 different 、 non-default 流中。

數(shù)據(jù)傳輸所涉及的主機內存必須是 pinned 內存。

因此,讓我們從上面修改我們的簡單主機代碼,以使用多個流,看看是否可以實現(xiàn)任何重疊。這個例子的完整代碼是 在 Github 上提供 。在修改后的代碼中,我們將大小為 N 的數(shù)組分解為 streamSize 元素的塊。由于內核對所有元素都是獨立操作的,因此每個塊都可以獨立處理。使用的(非默認)流數(shù)為 nStreams=N/streamSize 。有多種方法可以實現(xiàn)數(shù)據(jù)的域分解和處理;一種方法是循環(huán)使用數(shù)組中每個塊的所有操作,如本示例代碼所示。

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&d_a[offset], &a[offset], streamBytes, cudaMemcpyHostToDevice, stream[i]);
  kernel<<>>(d_a, offset);
  cudaMemcpyAsync(&a[offset], &d_a[offset], streamBytes, cudaMemcpyDeviceToHost, stream[i]);
}

另一種方法是將類似的操作批處理在一起,首先發(fā)出所有主機到設備的傳輸,然后是所有的內核啟動,然后是所有設備到主機的傳輸,如下面的代碼所示。

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&d_a[offset], &a[offset],
                  streamBytes, cudaMemcpyHostToDevice, cudaMemcpyHostToDevice, stream[i]);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  kernel<<>>(d_a, offset);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&a[offset], &d_a[offset],
                  streamBytes, cudaMemcpyDeviceToHost, cudaMemcpyDeviceToHost, stream[i]);
}

上面顯示的兩個異步方法都會產(chǎn)生正確的結果,并且在這兩種情況下,依賴操作都會按照它們需要執(zhí)行的順序發(fā)布到同一個流。但根據(jù)所使用的 GPU 的特定代數(shù),這兩種方法的性能截然不同。在 Tesla C1060 (計算能力 1 。 3 )上運行測試代碼(來自 Github )給出以下結果。

Device : Tesla C1060

Time for sequential transfer and execute (ms ): 12.92381
  max error : 2.3841858E -07
Time for asynchronous V1 transfer and execute (ms ): 13.63690
  max error : 2.3841858E -07
Time for asynchronous V2 transfer and execute (ms ): 8.84588
  max error : 2.3841858E -07

在 Tesla C2050 (計算能力 2 . 0 )上,我們得到以下結果。

Device : Tesla C2050

Time for sequential transfer and execute (ms ): 9.984512
  max error : 1.1920929e -07
Time for asynchronous V1 transfer and execute (ms ): 5.735584
  max error : 1.1920929e -07
Time for asynchronous V2 transfer and execute (ms ): 7.597984
  max error : 1.1920929e -07

這里第一次報告的是使用阻塞傳輸?shù)捻樞騻鬏敽蛢群藞?zhí)行,我們將其作為異步加速比較的基線。為什么這兩種異步策略在不同的體系結構上表現(xiàn)不同?要破解這些結果,我們需要更多地了解 CUDA 設備如何調度和執(zhí)行任務。 CUDA 設備包含用于各種任務的引擎,這些引擎在發(fā)出操作時對操作進行排隊。不同引擎中的任務之間的依賴關系得到維護,但是在任何引擎中,所有外部依賴關系都會丟失;每個引擎隊列中的任務將按照它們的發(fā)出順序執(zhí)行。 C1060 有一個拷貝引擎和一個內核引擎。在 C1060 上執(zhí)行示例代碼的時間線如下圖所示。

在這個示意圖中,我們假設主機到設備傳輸、內核執(zhí)行和設備到主機傳輸所需的時間大致相同(選擇內核代碼是為了實現(xiàn)這一點)。正如順序內核所期望的那樣,任何操作中都沒有重疊。對于我們代碼的第一個異步版本,復制引擎中的執(zhí)行順序是: H2D stream ( 1 )、 D2H stream ( 1 )、 H2D stream ( 2 )、 D2H stream ( 2 )等等。這就是為什么我們在 C1060 上使用第一個異步版本時看不到任何加速:任務是按照排除內核執(zhí)行和數(shù)據(jù)傳輸重疊的順序被發(fā)送到復制引擎的。然而,對于版本 2 ,在所有主機到設備的傳輸在任何設備到主機的傳輸之前發(fā)出,重疊是可能的,如較低的執(zhí)行時間所示。根據(jù)我們的示意圖,我們期望異步版本 2 的執(zhí)行時間是順序版本的 8 / 12 ,或者 8 。 7ms ,這在前面給出的計時結果中得到了確認。

在 C2050 上,兩個功能相互作用導致與 C1060 不同的行為。 C2050 有兩個復制引擎,一個用于主機到設備的傳輸,另一個用于設備到主機的傳輸,以及一個內核引擎。下圖說明了我們的示例在 C2050 上的執(zhí)行。

有兩個復制引擎解釋了為什么異步版本 1 在 C2050 上實現(xiàn)了很好的加速:流[i] 不阻止流中數(shù)據(jù)的主機到設備傳輸 [i + 1]中數(shù)據(jù)的主機到設備的傳輸,因為 C2050 上的每個復制方向都有一個單獨的引擎。示意圖預測了執(zhí)行情況相對于順序版本,時間被縮短一半,這大致就是我們的計時結果顯示的。

但是在 C2050 上的異步版本 2 中觀察到的性能下降呢?這與 C2050 并發(fā)運行多個內核的能力有關。當多個內核在不同(非默認)流中背靠背地發(fā)出時,調度程序嘗試啟用這些內核的并發(fā)執(zhí)行,結果會延遲通常在每個內核完成后出現(xiàn)的信號(這負責啟動設備到主機的傳輸),直到所有內核完成。因此,雖然在第二個版本的異步代碼中,主機到設備的傳輸和內核的執(zhí)行之間有重疊,但是內核執(zhí)行和設備到主機的傳輸之間沒有重疊。示意圖預測異步版本 2 的總時間是順序版本的 9 / 12 ,即 7 。 5 毫秒,這一點由我們的計時結果證實。

CUDA Fortran 異步數(shù)據(jù)傳輸 中提供了關于本文中使用的示例的更詳細的描述,好消息是對于具有計算能力 3 。 5 ( K20 系列)的設備, Hyper-Q 特性消除了定制發(fā)布順序的需要,因此上述任何一種方法都可以工作。我們將在以后的文章中討論使用開普勒特性,但是現(xiàn)在,這里是在 Tesla K20c GPU 上運行示例代碼的結果。如您所見,這兩個異步方法在同步代碼上實現(xiàn)了相同的加速。

Device : Tesla K20c
Time for sequential transfer and execute (ms): 7.101760
  max error : 1.1920929e -07
Time for asynchronous V1 transfer and execute (ms): 3.974144
  max error : 1.1920929e -07
Time for asynchronous V2 transfer and execute (ms): 3.967616
  max error : 1.1920929e -07

概括

這篇文章和 上一個 討論了如何優(yōu)化主機和設備之間的數(shù)據(jù)傳輸。上一篇文章集中討論了如何最小化執(zhí)行這種傳輸?shù)臅r間,這篇文章介紹了流,以及如何使用流通過并發(fā)執(zhí)行副本和內核來屏蔽數(shù)據(jù)傳輸時間。

在一篇關于流的文章中,我應該提到,雖然使用默認流可以方便地開發(fā)代碼,但同步代碼更簡單,最終您的代碼應該使用非默認流或 CUDA 7 對每線程默認流的支持(讀 GPU 專業(yè)提示: CUDA 7 流簡化并發(fā) )。這在編寫庫時尤其重要。如果庫中的代碼使用默認流,那么最終用戶就沒有機會將數(shù)據(jù)傳輸與庫內核執(zhí)行重疊。

現(xiàn)在您已經(jīng)知道如何在主機和設備之間高效地移動數(shù)據(jù),所以我們將研究如何在 下一篇文章 中的內核中高效地訪問數(shù)據(jù)。

關于作者

Mark Harris 是 NVIDIA 杰出的工程師,致力于 RAPIDS 。 Mark 擁有超過 20 年的 GPUs 軟件開發(fā)經(jīng)驗,從圖形和游戲到基于物理的模擬,到并行算法和高性能計算。當他還是北卡羅來納大學的博士生時,他意識到了一種新生的趨勢,并為此創(chuàng)造了一個名字: GPGPU (圖形處理單元上的通用計算)。

審核編輯:郭婷

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • NVIDIA
    +關注

    關注

    14

    文章

    5026

    瀏覽量

    103298
  • gpu
    gpu
    +關注

    關注

    28

    文章

    4754

    瀏覽量

    129096
  • C++
    C++
    +關注

    關注

    22

    文章

    2112

    瀏覽量

    73734
收藏 人收藏

    評論

    相關推薦

    MPU數(shù)據(jù)傳輸協(xié)議詳解

    在現(xiàn)代電子系統(tǒng),微控制器(MPU)扮演著核心角色,負責處理各種任務和數(shù)據(jù)。為了實現(xiàn)這些功能,MPU需要與其他設備進行數(shù)據(jù)交換。
    的頭像 發(fā)表于 01-08 09:37 ?95次閱讀

    ptp對實時數(shù)據(jù)傳輸的影響

    在現(xiàn)代通信技術,點對點(P2P)網(wǎng)絡已經(jīng)成為數(shù)據(jù)傳輸的一種重要方式。P2P網(wǎng)絡允許網(wǎng)絡的每個節(jié)點既可以作為客戶端也可以作為服務器,直接進行數(shù)據(jù)交換。這種去中心化的網(wǎng)絡結構對于實時
    的頭像 發(fā)表于 12-29 09:53 ?157次閱讀

    PCIe數(shù)據(jù)傳輸協(xié)議詳解

    、網(wǎng)卡和聲卡等,以實現(xiàn)高效的數(shù)據(jù)傳輸。以下是對PCIe數(shù)據(jù)傳輸協(xié)議的介紹: 一、PCIe協(xié)議的基本概念 PCIe協(xié)議定義了一系列規(guī)范和要求,以實現(xiàn)在主機系統(tǒng)和外圍設備之間高效、可靠地進
    的頭像 發(fā)表于 11-26 16:12 ?1300次閱讀

    socket 數(shù)據(jù)傳輸效率提升技巧

    在現(xiàn)代網(wǎng)絡應用數(shù)據(jù)傳輸效率是衡量系統(tǒng)性能的關鍵指標之一。對于使用socket進行數(shù)據(jù)傳輸的應用,優(yōu)化傳輸效率不僅可以提升用戶體驗,還能降低成本。 1. 選擇合適的
    的頭像 發(fā)表于 11-12 14:34 ?407次閱讀

    CAN總線數(shù)據(jù)傳輸速率設置

    CAN(Controller Area Network)總線是一種串行通信協(xié)議,主要用于汽車和工業(yè)控制系統(tǒng),以實現(xiàn)電子控制單元(ECU)之間的通信。CAN總線的數(shù)據(jù)傳輸速率,也稱為波特率,是衡量
    的頭像 發(fā)表于 11-12 10:03 ?794次閱讀

    LORA模塊的數(shù)據(jù)傳輸速率

    有所不同。以下是關于LoRa模塊數(shù)據(jù)傳輸速率的一些關鍵點: 數(shù)據(jù)傳輸速率的可變性 : LoRa技術允許在不同的數(shù)據(jù)速率下操作,以適應不同的應用需求。速率可以從幾百比特每秒(bps)到幾
    的頭像 發(fā)表于 10-31 17:03 ?1088次閱讀

    網(wǎng)絡數(shù)據(jù)傳輸速率的單位是什么

    網(wǎng)絡數(shù)據(jù)傳輸速率的單位是 bps(bit per second) ,即比特每秒,也可以表示為b/s或bit/s。它表示的是每秒鐘傳輸的二進制數(shù)的位數(shù)。比特(bit)是計算機數(shù)據(jù)量的單
    的頭像 發(fā)表于 10-12 10:20 ?1469次閱讀

    高速串行總線,數(shù)據(jù)傳輸離不開它!#高速串行總線 #電路知識 #數(shù)據(jù)傳輸

    電路數(shù)據(jù)傳輸
    安泰儀器維修
    發(fā)布于 :2024年08月20日 15:42:00

    C++實現(xiàn)類似instanceof的方法

    函數(shù),可實際上C++沒有。但是別著急,其實C++中有兩種簡單的方法可以實現(xiàn)類似Java的instanceof的功能。 在
    的頭像 發(fā)表于 07-18 10:16 ?619次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>中</b><b class='flag-5'>實現(xiàn)</b>類似instanceof的方法

    邊OTG邊充電芯片如何實現(xiàn)充電與數(shù)據(jù)傳輸并行?

    邊OTG邊充電芯片實現(xiàn)充電與數(shù)據(jù)傳輸并行的功能,主要依賴于其內部的設計和與USB Type-C接口標準的結合。
    的頭像 發(fā)表于 07-14 10:35 ?620次閱讀

    以太網(wǎng)接口的數(shù)據(jù)傳輸原理詳解

    以太網(wǎng)接口作為計算機網(wǎng)絡的關鍵組成部分,承擔著數(shù)據(jù)傳輸的重要職責。在了解以太網(wǎng)接口的數(shù)據(jù)傳輸原理之前,我們首先需要明確以太網(wǎng)的基本概念和工作機制。以太網(wǎng)是一種廣泛應用的局域網(wǎng)技術,它基于CSMA
    的頭像 發(fā)表于 05-29 16:47 ?1734次閱讀

    探索SPI單線傳輸模式時鐘線與數(shù)據(jù)傳輸的簡化

    通信的簡化需求也日益增加。在這種背景下,SPI的單線傳輸模式成為了一個備受關注的解決方案。 SPI協(xié)議概述 SPI協(xié)議是一種常用的同步串行通信協(xié)議,通常用于微控制器與其他設備之間的數(shù)據(jù)傳輸。它基于主從架構,允許一個主機與多個從機
    的頭像 發(fā)表于 05-28 18:26 ?1211次閱讀

    GMSL技術 實現(xiàn)高帶寬、低延遲和高可靠性數(shù)據(jù)傳輸# ADI# GMSL# 汽車# 數(shù)據(jù)傳輸

    adi數(shù)據(jù)傳輸電機
    Excelpoint世健
    發(fā)布于 :2024年05月17日 16:34:25

    DTU的多種協(xié)議,解鎖數(shù)據(jù)傳輸的無限可能

    DTU,即數(shù)據(jù)傳輸單元,是一種在物聯(lián)網(wǎng)(IoT)網(wǎng)絡中常用的設備,主要用于在傳感器和智能設備之間進行數(shù)據(jù)傳輸。DTU使用多種協(xié)議來實現(xiàn)這一目標,這些協(xié)議不僅提高了數(shù)據(jù)傳輸的效率,還增強
    的頭像 發(fā)表于 03-01 11:00 ?860次閱讀
    DTU的多種協(xié)議,解鎖<b class='flag-5'>數(shù)據(jù)傳輸</b>的無限可能

    兩路數(shù)據(jù)傳輸,CY7C68013都作為從機接收數(shù)據(jù)是否可行?

    我想使用CY7C68013A的GPIF和FIFO功能: 1. 兩路數(shù)據(jù)傳輸,CY7C68013都作為從機接收數(shù)據(jù) 2. 每一路都數(shù)據(jù)格式為:
    發(fā)表于 02-28 07:34
    主站蜘蛛池模板: yezhulu在线永久网址yellow| 黄黄网| 国产精品嫩草影院一二三区 | 亚洲精品卡1卡二卡3卡四卡 | 国产一卡二卡≡卡四卡无人| 久久久精品免费视频| 激情.com| 377p亚洲欧洲日本大胆色噜噜| 一级一黄在线观看视频免费| 黄色毛片免费| 欧洲人体超大胆露私视频| 欧美一级视频在线观看| 免费一级毛片视频| 色老太视频| 一级特黄aa大片| 午夜爱爱网站| 欧美一级艳片视频免费观看| 六月婷婷激情| 成年片免费网址网站| 国产精品入口免费视频| 6969精品视频在线观看| 天堂网www中文天堂在线| 丁香天堂网| 羞羞视频靠逼视频大全| 中文字字幕码一二区| 欧美色网在线| 欧美性色黄大片四虎影视| 亚洲电影免费| 欧美巨大bbbb动漫| 男人的天堂免费视频| 国产成人小视频| 日韩一级特黄| 久久久国产乱子伦精品| 男人天堂网址| 久操视频免费观看| 在线三区| 轻点灬大ji巴太粗太长了啊h| 亚洲人成人| 亚欧人成精品免费观看| 五月婷花| 色婷婷丁香|