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

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

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

3天內不再提示

如何在CUDA C/C++中實現主機和設備同步執行

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

在 本系列文章的第一篇 中,我們通過檢查 CUDA C/C++ SAXPY 來研究 CUDA C / C ++的基本元素。在第二篇文章中,我們將討論如何分析這個和其他 CUDA C / C ++代碼的性能。我們將依賴于這些性能測量技術在未來的職位,性能優化將變得越來越重要。

CUDA 性能度量通常是從主機代碼中完成的,可以使用 CPU 計時器或 CUDA 特定計時器來實現。在討論這些性能度量技術之前,我們需要討論如何在主機和設備之間同步執行。

主機設備同步

讓我們看看數據傳輸和來自上一篇文章的 SAXPY 主機代碼的內核啟動:

cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);

cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);



saxpy<<<(N+255)/256, 256>>>(N, 2.0, d_x, d_y);



cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);

使用cudaMemcpy()在主機和設備之間的數據傳輸是synchronous(或blocking)傳輸。同步數據傳輸在之前發出的所有 CUDA 調用完成之前不會開始,后續的 CUDA 調用在同步傳輸完成之前無法開始。因此,第三行的saxpy內核啟動在第二行從yd_y的傳輸完成后才會發出。另一方面,內核啟動是異步的。一旦內核在第三行啟動,控制權立即返回到 CPU ,而不是等待內核完成。而 MIG ht 似乎為設備在最后一行主機數據傳輸設置了一個競爭條件,數據傳輸的阻塞性質確保了內核在傳輸開始之前完成。

用 CPU 計時器計時內核執行

現在讓我們來看看如何使用 CPU 計時器為內核執行計時。

cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);

cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);



t1 = myCPUTimer();

saxpy<<<(N+255)/256, 256>>>(N, 2.0, d_x, d_y);

cudaDeviceSynchronize();

t2 = myCPUTimer();



cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);

除了對通用主機時間戳函數myCPUTimer()的兩次調用外,我們還使用顯式同步屏障cudaDeviceSynchronize()來阻止 CPU 的執行,直到設備上以前發出的所有命令都已完成。如果沒有這個屏障,這段代碼將測量內核發射時間,而不是內核執行時間

使用 CUDA 事件計時

使用主機設備同步點(如cudaDeviceSynchronize()的一個問題是它們會暫停 GPU 管道。因此, CUDA 通過CUDA 事件 API為 CPU 定時器提供了一個相對輕量級的替代方案。 CUDA 事件 API 包括在兩個記錄的事件之間調用create破壞事件、record事件和以毫秒為單位計算已用時間

CUDA 事件利用?CUDA?streams. CUDA 流只是按順序在設備上執行的操作序列。在某些情況下[vx3 . 4 可以交叉使用 vx3 . 4]的流。到目前為止, GPU 上的所有操作都發生在默認流或流 0 (也稱為“空流”)中。

在下面的清單中,我們將 CUDA 事件應用于 SAXPY 代碼。

cudaEvent_t start, stop;

cudaEventCreate(&start);

cudaEventCreate(&stop);



cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);

cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);



cudaEventRecord(start);

saxpy<<<(N+255)/256, 256>>>(N, 2.0f, d_x, d_y);

cudaEventRecord(stop);



cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);



cudaEventSynchronize(stop);

float milliseconds = 0;

cudaEventElapsedTime(&milliseconds, start, stop);

CUDA 事件屬于cudaEvent_t類型,使用cudaEventCreate()cudaEventDestroy()創建和銷毀事件。在上面的代碼中cudaEventRecord()將啟動和停止事件放入默認流 stream 0 。當事件到達流中的事件時,設備將記錄事件的時間戳。函數cudaEventSynchronize()會阻止 CPU 的執行,直到記錄指定的事件為止。cudaEventElapsedTime()函數在第一個參數中返回錄制startstop之間經過的毫秒數。該值的分辨率約為半微秒。

內存帶寬

現在我們有了一種精確計時內核執行的方法,我們將使用它來計算帶寬。在評估帶寬效率時,我們同時使用理論峰值帶寬和觀察到的或有效的內存帶寬。

理論帶寬

理論帶寬可以使用產品文獻中提供的硬件規格計算。例如, NVIDIA Tesla M2050 GPU 使用內存時鐘速率為 1546 MHz 的 DDR (雙數據速率) RAM 和 384 位寬的內存接口。使用這些數據項, NVIDIA Tesla M2050 的峰值理論內存帶寬為 148 GB / s ,如下所示。

BWTheoretical= 1546 * 106* (384 / 8) * 2 / 109= 148 GB / s

在這個計算中,我們將內存時鐘速率轉換為赫茲,乘以接口寬度(除以 8 ,將位轉換為字節),再乘以 2 ,這是由于數據速率加倍。最后,我們除以 109將結果轉換為 GB / s 。

有效帶寬

我們通過計時特定的程序活動和了解程序如何訪問數據來計算有效帶寬。我們用下面的等式。

BWEffective=(RB+WB( VZX50]* 109)

這里,BWEffective有效帶寬,單位為 GB / s ,RB是每個內核讀取的字節數,WB是每個內核寫入的字節數,t是以秒為單位的運行時間。下面是完整的代碼。

#include



__global__

void saxpy(int n, float a, float *x, float *y)

{

  int i = blockIdx.x*blockDim.x + threadIdx.x;

  if (i < n) y[i] = a*x[i] + y[i];

}



int main(void)

{

  int N = 20 * (1 << 20);

  float *x, *y, *d_x, *d_y;

  x = (float*)malloc(N*sizeof(float));

  y = (float*)malloc(N*sizeof(float));



  cudaMalloc(&d_x, N*sizeof(float));

  cudaMalloc(&d_y, N*sizeof(float));



  for (int i = 0; i < N; i++) {

    x[i] = 1.0f;

    y[i] = 2.0f;

  }



  cudaEvent_t start, stop;

  cudaEventCreate(&start);

  cudaEventCreate(&stop);



  cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);

  cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);



  cudaEventRecord(start);



  // Perform SAXPY on 1M elements

  saxpy<<<(N+511)/512, 512>>>(N, 2.0f, d_x, d_y);



  cudaEventRecord(stop);



  cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);



  cudaEventSynchronize(stop);

  float milliseconds = 0;

  cudaEventElapsedTime(&milliseconds, start, stop);



  float maxError = 0.0f;

  for (int i = 0; i < N; i++) {

    maxError = max(maxError, abs(y[i]-4.0f));

  }



  printf("Max error: %fn", maxError);

  printf("Effective Bandwidth (GB/s): %fn", N*4*3/milliseconds/1e6);

}

在帶寬計算中,N*4是每個數組讀或寫傳輸的字節數, 3 的因子表示x的讀取和y的讀寫。經過的時間存儲在變量milliseconds中,以明確單位。請注意,除了添加帶寬計算所需的功能外,我們還更改了數組大小和線程塊大小。在 Tesla M2050 上編譯并運行此代碼:

$ ./saxpy

Max error: 0.000000

Effective Bandwidth (GB/s): 110.374872

測量計算吞吐量

我們剛剛演示了如何測量帶寬,帶寬是數據吞吐量的度量。另一個對性能非常重要的指標是計算吞吐量。計算吞吐量的常用度量是 GFLOP / s ,它代表“每秒千兆浮點運算”,其中 Giga 是 10 的前綴9. 我們通常測量 SAXPY 的吞吐量,因為每一個 SAXPY 運算都是有效的

GFLOP/s Effective== 2 N /( t :《* 109)

N 是 SAXPY 操作中的元素數, t 是以秒為單位的運行時間。與理論峰值帶寬一樣,理論峰值 GFLOP / s 可以從產品文獻中獲得(但是計算它可能有點棘手,因為它與體系結構非常相關)。例如, Tesla M2050 GPU 的單精度浮點吞吐量理論峰值為 1030 GFLOP / s ,雙倍精度的理論峰值吞吐量為 515 GFLOP / s 。

SAXPY 為計算的每個元素讀取 12 個字節,但是只執行一個乘法加法指令( 2 個浮點運算),因此很明顯它是帶寬受限的,因此在這種情況下(實際上在許多情況下),帶寬是衡量和優化的最重要的指標。在更復雜的計算中,在 FLOPs 級別測量性能可能非常困難。因此,更常見的是使用分析工具來了解計算吞吐量是否是一個瓶頸。應用程序通常提供特定于問題(而不是特定于體系結構)的吞吐量指標,因此對用戶更有用。例如,天文 n 體問題的“每秒十億次相互作用”,或分子動力學模擬的“每天納秒”。

總結

這篇文章描述了如何使用 CUDA 事件 API 為內核執行計時。 CUDA 事件使用 GPU 計時器,因此避免了與主機設備同步相關的問題。我們提出了有效帶寬和計算吞吐量性能指標,并在 SAXPY 內核中實現了有效帶寬。很大一部分內核是內存帶寬限制的,因此計算有效帶寬是性能優化的第一步。在以后的文章中,我們將討論如何確定帶寬、指令或延遲是性能的限制因素。

CUDA 事件還可以用于確定主機和設備之間的數據傳輸速率,方法是在 cudaMemcpy() 調用的任一側記錄事件。

如果你在這個設備上運行一個關于內存不足的錯誤[ZC9],你可能會得到一個更小的錯誤。實際上,到目前為止,我們的示例代碼還沒有費心檢查運行時錯誤。在[VZX337]中,我們將學習如何在 CUDA C / C ++中執行錯誤處理以及如何查詢當前設備以確定它們可用的資源,以便我們可以編寫更健壯的代碼。

關于作者

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

審核編輯:郭婷

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

    關注

    28

    文章

    4788

    瀏覽量

    129416
  • API
    API
    +關注

    關注

    2

    文章

    1518

    瀏覽量

    62451
  • 計時器
    +關注

    關注

    1

    文章

    426

    瀏覽量

    32878
收藏 人收藏

    評論

    相關推薦

    Spire.XLS for C++組件說明

    Spire.XLS for C++ 是一款專業的 C++ Excel 組件,可以用在各種 C++ 框架和應用程序。Spire.XLS for C+
    的頭像 發表于 01-14 09:40 ?167次閱讀
    Spire.XLS for <b class='flag-5'>C++</b>組件說明

    EE-112:模擬C++的類實現

    電子發燒友網站提供《EE-112:模擬C++的類實現.pdf》資料免費下載
    發表于 01-03 15:15 ?0次下載
    EE-112:模擬<b class='flag-5'>C++</b><b class='flag-5'>中</b>的類<b class='flag-5'>實現</b>

    C7000 C/C++優化指南用戶手冊

    電子發燒友網站提供《C7000 C/C++優化指南用戶手冊.pdf》資料免費下載
    發表于 11-09 15:00 ?0次下載
    <b class='flag-5'>C</b>7000 <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>優化指南用戶手冊

    TMS320C6000優化C/C++編譯器v8.3.x

    電子發燒友網站提供《TMS320C6000優化C/C++編譯器v8.3.x.pdf》資料免費下載
    發表于 11-01 09:35 ?0次下載
    TMS320<b class='flag-5'>C</b>6000優化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器v8.3.x

    C語言和C++結構體的區別

    同樣是結構體,看看在C語言和C++中有什么區別?
    的頭像 發表于 10-30 15:11 ?363次閱讀

    C7000優化C/C++編譯器

    電子發燒友網站提供《C7000優化C/C++編譯器.pdf》資料免費下載
    發表于 10-30 09:45 ?0次下載
    <b class='flag-5'>C</b>7000優化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器

    ostream在c++的用法

    ostream 是 C++ 標準庫中一個非常重要的類,它位于 頭文件(實際上,更常見的是通過包含 頭文件來間接包含 ,因為 包含了 和 )。 ostream 類及其派生類(如 std::cout
    的頭像 發表于 09-20 15:11 ?987次閱讀

    C++語言基礎知識

    電子發燒友網站提供《C++語言基礎知識.pdf》資料免費下載
    發表于 07-19 10:58 ?8次下載

    C++實現類似instanceof的方法

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

    FX2 CY7C68013A如何在C++環境中使用LoadEEPROM函數?

    我使用的是 FX2 CY7C68013A 芯片。 我知道 CyUSB.NET 庫中有我需要的 LoadEEPROM 函數。 請問如何在 C++ 環境而不是 C#/CLR 環境中使用該函
    發表于 05-31 06:59

    何在FX3 SuperSpeed explorer等電路板上使用openOCD調試C++項目?

    配置與文檔的完全相同。 因此,我想請教如何在 FX3 SuperSpeed explorer 等電路板上使用 openOCD 調試我的 C++ 項目? 回到純 C 項目并不是一個真正
    發表于 05-23 08:16

    C/C++兩種宏實現方式

    #ifndef的方式受C/C++語言標準支持。它不僅可以保證同一個文件不會被包含多次,也能保證內容完全相同的兩個文件(或者代碼片段)不會被不小心同時包含。
    的頭像 發表于 04-19 11:50 ?710次閱讀

    C/C++代碼動態測試工具VectorCAST插樁功能演示#代碼動態測試 #C++

    C++代碼
    北匯信息POLELINK
    發布于 :2024年04月18日 11:57:45

    鴻蒙OS開發實例:【Native C++

    使用DevEco Studio創建一個Native C++應用。應用采用Native C++模板,實現使用NAPI調用C標準庫的功能。使用C
    的頭像 發表于 04-14 11:43 ?2794次閱讀
    鴻蒙OS開發實例:【Native <b class='flag-5'>C++</b>】

    使用 MISRA C++:2023? 避免基于范圍的 for 循環中的錯誤

    在前兩篇博客,我們?向您介紹了新的 MISRA C++ 標準?和?C++ 的歷史?。在這篇博客,我們將仔細研究以 C++
    的頭像 發表于 03-28 13:53 ?873次閱讀
    使用 MISRA <b class='flag-5'>C++</b>:2023? 避免基于范圍的 for 循環中的錯誤
    主站蜘蛛池模板: 久久亚洲国产成人精品性色 | 六月丁香六月婷婷 | 人人干人人干人人干 | 高清午夜毛片 | 美女免费视频黄 | 免费黄色福利视频 | 精品99久久 | 高清性色生活片欧美在线 | 人人人人草| 一级毛片aaaaaa视频免费看 | 五月.com| 午夜精品久久久久久久99 | 天天干视频网站 | 五月婷婷之综合激情 | 国产黄色网页 | 亚洲伊人成综合成人网 | xxxx日本xx | 婷婷久久久五月综合色 | 免费永久欧美性色xo影院 | 黄色免费网站视频 | 欧美国产精品主播一区 | 香蕉久久夜色精品国产小说 | 三级视频网站在线观看 | 欧美高清成人 | 国产小视频网站 | 色噜噜成人综合网站 | 国产一区二区精品 | 亚洲国产婷婷香蕉久久久久久 | 影音先锋在线亚洲精品推荐 | 年轻的护士3 | 久久久久久久综合色一本 | 久久国产成人午夜aⅴ影院 久久国产福利 | 2021国产精品午夜久久 | 国产精品第一页在线观看 | 日日操操干干 | 97人人模人人揉人人捏 | 亚洲天堂h | 日韩三级小视频 | 一级做a爱片久久毛片 | 白嫩美女一级高清毛片免费看 | 成人免费久久精品国产片久久影院 |