精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

CPU與GPPU架構比較分析 在GPU上執行Kernel的具體步驟

sakobpqhz ? 來源:算力基建 ? 2023-11-05 11:33 ? 次閱讀

大多數工程師CPU和順序編程都十分熟悉,這是因為自從他們開始編寫CPU代碼以來,就與之密切接觸。然而,對于GPU的內部工作原理及其獨特之處,他們的了解則相對較少。過去十年,由于GPU在深度學習中得到廣泛應用而變得極為重要。因此,每位軟件工程師都有必要了解其基本工作原理。本文旨在為讀者提供這方面的背景知識。

本文作者為軟件工程師Abhinav Upadhyay,他在《大規模并行處理器編程》第四版(Hwu等)的基礎上編寫了本文大部分內容,其中介紹了包括GPU體系結構和執行模型等內容。當然,文中GPU編程的基本概念和方法同樣適用于其他供應商的產品

01. 比較CPU與GPU

首先,我們會比較CPU和GPU,這能幫助我們更好地了解GPU的發展狀況,但這應該作為一個獨立的主題,因為我們難以在一節中涵蓋其所有的內容。因此,我們將著重介紹一些關鍵點。

CPU和GPU的主要區別在于它們的設計目標。CPU的設計初衷是執行順序指令[1]。一直以來,為提高順序執行性能,CPU設計中引入了許多功能。其重點在于減少指令執行時延,使CPU能夠盡可能快地執行一系列指令。這些功能包括指令流水線、亂序執行、預測執行和多級緩存等(此處僅列舉部分)。

而GPU則專為大規模并行和高吞吐量而設計,但這種設計導致了中等至高程度的指令時延。這一設計方向受其在視頻游戲、圖形處理、數值計算以及現如今的深度學習中的廣泛應用所影響,所有這些應用都需要以極高的速度執行大量線性代數和數值計算,因此人們傾注了大量精力以提升這些設備的吞吐量。

我們來思考一個具體的例子:由于指令時延較低,CPU在執行兩個數字相加的操作時比GPU更快。在按順序執行多個這樣的計算時,CPU能夠比GPU更快地完成。然而,當需要進行數百萬甚至數十億次這樣的計算時,由于GPU具有強大的大規模并行能力,它將比CPU更快地完成這些計算任務。

我們可以通過具體數據來進行說明。硬件在數值計算方面的性能以每秒浮點運算次數(FLOPS)來衡量。NVIDIA的Ampere A100在32位精度下的吞吐量為19.5 TFLOPS。相比之下,Intel的24核處理器在32位精度下的吞吐量僅為0.66 TFLOPS(2021年)。同時,隨時間推移,GPU與CPU在吞吐量性能上的差距逐年擴大。

下圖對CPU和GPU的架構進行了比較。

wKgaomVHDQuAfDV4AAFyqSOVw2E164.png

圖1:CPU與GPU的芯片設計對比。引自《CUDA C++編程指南》(NVIDIA)

如圖所示,CPU在芯片領域中主要用于降低指令時延的功能,例如大型緩存、較少的算術邏輯單元(ALU)和更多的控制單元。與此相比,GPU則利用大量的ALU來最大化計算能力和吞吐量,只使用極小的芯片面積用于緩存和控制單元,這些元件主要用于減少CPU時延。

時延容忍度和高吞吐量

或許你會好奇,GPU如何能夠容忍高時延并同時提供高性能呢?GPU 擁有大量線程和強大的計算能力,使這一點成為可能。即使單個指令具有高延遲,GPU 也會有效地調度線程運行,以便它們在任意時間點都能利用計算能力。例如,當某些線程正在等待指令結果時,GPU 將切換到運行其他非等待線程。這可確保 GPU 上的計算單元在所有時間點都以其最大容量運行,從而提供高吞吐量。稍后當我們討論kernel如何在 GPU 上運行時,我們將對此有更清晰的了解。

02. GPU架構

我們已經了解到GPU有利于實現高吞吐量,但它們是通過怎樣的架構來實現這一目標的呢?本節將對此展開探討。

GPU的計算架構

GPU由一系列流式多處理器(SM)組成,其中每個SM又由多個流式處理器、核心或線程組成。例如,NVIDIA H100 GPU具有132個SM,每個SM擁有64個核心,總計核心高達8448個。

每個SM都擁有一定數量的片上內存(on-chip memory),通常稱為共享內存或臨時存儲器,這些共享內存被所有的核心所共享。同樣,SM上的控制單元資源也被所有的核心所共享。此外,每個SM都配備了基于硬件的線程調度器,用于執行線程。

除此之外,每個SM還配備了幾個功能單元或其他加速計算單元,例如張量核心(tensor core)或光線追蹤單元(ray tracing unit),用于滿足GPU所處理的工作負載的特定計算需求。

wKgZomVHDQuANPbxAABh9VnnJHs828.png

圖2:GPU的計算架構

接下來,讓我們深入剖析GPU內存并了解其中的細節。

GPU的內存架構

GPU具有多層不同類型的內存,每一層都有其特定用途。下圖顯示了GPU中一個SM的內存層次結構。

wKgZomVHDQuAEkIHAAEmwbORS2o004.jpg

圖3:基于康奈爾大學虛擬工作坊(Virtual Workshop)的GPU內存架構

讓我們對其進行剖析:

寄存器:讓我們從寄存器開始。GPU中的每個SM都擁有大量寄存器。例如,NVIDIA的A100和H100模型中,每個SM擁有65536個寄存器。這些寄存器在核心之間共享,并根據線程需求動態分配。在執行過程中,每個線程都被分配了私有寄存器,其他線程無法讀取或寫入這些寄存器。

常量緩存:接下來是芯片上的常量緩存。這些緩存用于緩存SM上執行的代碼中使用的常量數據。為利用這些緩存,程序員需要在代碼中明確將對象聲明為常量,以便GPU可以將其緩存并保存在常量緩存中。

共享內存:每個SM還擁有一塊共享內存或臨時內存,它是一種小型、快速且低時延的片上可編程SRAM內存,供運行在SM上的線程塊共享使用。共享內存的設計思路是,如果多個線程需要處理相同的數據,只需要其中一個線程從全局內存(global memory)加載,而其他線程將共享這一數據。合理使用共享內存可以減少從全局內存加載重復數據的操作,并提高內核執行性能。共享內存還可以用作線程塊(block)內的線程之間的同步機制。

L1緩存:每個SM還擁有一個L1緩存,它可以緩存從L2緩存中頻繁訪問的數據。

L2緩存:所有SM都共享一個L2緩存,它用于緩存全局內存中被頻繁訪問的數據,以降低時延。需要注意的是,L1和L2緩存對于SM來說是公開的,也就是說,SM并不知道它是從L1還是L2中獲取數據。SM從全局內存中獲取數據,這類似于CPU中L1/L2/L3緩存的工作方式。

全局內存:GPU還擁有一個片外全局內存,它是一種容量大且帶寬高的動態隨機存取存儲器(DRAM)。例如,NVIDIA H100擁有80 GB高帶寬內存(HBM),帶寬達每秒3000 GB。由于與SM相距較遠,全局內存的時延相當高。然而,芯片上還有幾個額外的存儲層以及大量的計算單元有助于掩飾這種時延。

現在我們已經了解GPU硬件的關鍵組成部分,接下來我們深入一步,了解執行代碼時這些組件是如何發揮作用的。

03. 了解GPU的執行模型

要理解GPU如何執行kernel,我們首先需要了解什么是kernel及其配置。

CUDA Kernel與線程塊簡介

CUDA是NVIDIA提供的編程接口,用于編寫運行在其GPU上的程序。在CUDA中,你會以類似于C/C++函數的形式來表達想要在GPU上運行的計算,這個函數被稱為kernel。kernel在并行中操作向量形式的數字,這些數字以函數參數的形式提供給它。一個簡單的例子是執行向量加法的kernel,即接受兩個向量作為輸入,逐元素相加,并將結果寫入第三個向量。

要在GPU上執行kernel,我們需要啟用多個線程,這些線程總體上被稱為一個網格(grid),但網格還具有更多的結構。一個網格由一個或多個線程塊(有時簡稱為塊)組成,而每個線程塊又由一個或多個線程組成。

線程塊和線程的數量取決于數據的大小和我們所需的并行度。例如,在向量相加的示例中,如果我們要對256維的向量進行相加運算,那么可以配置一個包含256個線程的單個線程塊,這樣每個線程就可以處理向量的一個元素。如果數據更大,GPU上也許沒有足夠的線程可用,這時我們可能需要每個線程能夠處理多個數據點。

wKgZomVHDQuATMOGAAFPjwu_cvo910.png

圖4:線程塊網格。引自《CUDA C++編程指南》(NVIDIA)

編寫一個kernel需要兩步。第一步是運行在CPU上的主機代碼,這部分代碼用于加載數據,為GPU分配內存,并使用配置的線程網格啟動kernel;第二步是編寫在GPU上執行的設備(GPU)代碼。

對于向量加法示例,下圖顯示了主機代碼。

wKgaomVHDQyAF2E6AAFrD226yJQ163.jpg

圖 5:CUDA kernel的主機代碼,用于將兩個向量相加。

下圖為設備代碼,它定義了實際的kernel函數。

wKgaomVHDQuAYj83AAD8diEfpvk189.jpg

圖 6:包含向量相加kernel定義的設備代碼。

由于本文的重點不在于教授CUDA,因此我們不會更深入地討論此段代碼。現在,讓我們看看在GPU上執行kernel的具體步驟。

04. 在GPU上執行Kernel的步驟

1. 將數據從主機復制到設備

在調度執行kernel之前,必須將其所需的全部數據從主機(即CPU)內存復制到GPU的全局內存(即設備內存)。盡管如此,在最新的GPU硬件中,我們還可以使用統一虛擬內存直接從主機內存中讀取數據(可參閱論文《EMOGI: Efficient Memory-access for Out-of-memory Graph-traversal in GPUs》)。

2. SM上線程塊的調度

當GPU的內存中擁有全部所需的數據后,它會將線程塊分配給SM。同一個塊內的所有線程將同時由同一個SM進行處理。為此,GPU必須在開始執行線程之前在SM上為這些線程預留資源。在實際操作中,可以將多個線程塊分配給同一個SM以實現并行執行。

wKgaomVHDQyAYZyAAABQHkqcH_A786.png

圖 7:將線程塊分配給SM

由于SM的數量有限,而大型kernel可能包含大量線程塊,因此并非所有線程塊都可以立即分配執行。GPU會維護一個待分配和執行的線程塊列表,當有任何一個線程塊執行完成時,GPU會從該列表中選擇一個線程塊執行。

單指令多線程 (SIMT) 和線程束(Warp)

眾所周知,一個塊(block)中的所有線程都會被分配到同一個SM上。但在此之后,線程還會進一步劃分為大小為32的組(稱為warp[2]),并一起分配到一個稱為處理塊(processing block)的核心集合上進行執行。

SM通過獲取并向所有線程發出相同的指令,以同時執行warp中的所有線程。然后這些線程將在數據的不同部分,同時執行該指令。在向量相加的示例中,一個warp中的所有線程可能都在執行相加指令,但它們會在向量的不同索引上進行操作。

由于多個線程同時執行相同的指令,這種warp的執行模型也稱為單指令多線程 (SIMT)。這類似于CPU中的單指令多數據(SIMD)指令。

Volta及其之后的新一代GPU引入了一種替代指令調度的機制,稱為獨立線程調度(Independent Thread Scheduling)。它允許線程之間完全并發,不受warp的限制。獨立線程調度可以更好地利用執行資源,也可以作為線程之間的同步機制。本文不會涉及獨立線程調度的相關內容,但你可以在CUDA編程指南中了解更多相關信息

4. Warp調度和時延容忍度

關于warp的運行原理,有一些值得討論的有趣之處。

即使SM內的所有處理塊(核心組)都在處理warp,但在任何給定時刻,只有其中少數塊正在積極執行指令。因為SM中可用的執行單元數量是有限的。

有些指令的執行時間較長,這會導致warp需要等待指令結果。在這種情況下,SM會將處于等待狀態的warp休眠,并執行另一個不需要等待任何結果的warp。這使得GPU能夠最大限度地利用所有可用計算資源,并提高吞吐量。

零計算開銷調度:由于每個warp中的每個線程都有自己的一組寄存器,因此SM從執行一個warp切換到另一個warp時沒有額外計算開銷。

與CPU上進程之間的上下文切換方式(context-switching)不同。如果一個進程需要等待一個長時間運行的操作,CPU在此期間會在該核心上調度執行另一個進程。然而,在CPU中進行上下文切換的代價昂貴,這是因為CPU需要將寄存器狀態保存到主內存中,并恢復另一個進程的狀態。

5. 將結果數據從設備復制到主機內存

最后,當kernel的所有線程都執行完畢后,最后一步就是將結果復制回主機內存。

盡管我們涵蓋了有關典型kernel執行的全部內容,但還有一點值得討論:動態資源分區。

05. 資源劃分和占用概念

我們通過一個稱為“occupancy(占用率)”的指標來衡量GPU資源的利用率,它表示分配給SM的warp數量與SM所能支持的最大warp數量之間的比值。為實現最大吞吐量,我們希望擁有100%的占用率。然而,在實踐中,由于各種約束條件,這并不容易實現。

為什么我們無法始終達到100%的占用率呢?SM擁有一組固定的執行資源,包括寄存器、共享內存、線程塊槽和線程槽。這些資源根據需求和GPU的限制在線程之間進行動態劃分。例如,在NVIDIA H100上,每個SM可以處理32個線程塊、64個warp(即2048個線程),每個線程塊擁有1024個線程。如果我們啟動一個包含1024個線程的網格,GPU將把2048個可用線程槽劃分為2個線程塊。

動態分區vs固定分區:動態分區能夠更為有效地利用GPU的計算資源。相比之下,固定分區為每個線程塊分配了固定數量的執行資源,這種方式并不總是最有效的。在某些情況下,固定分區可能會導致線程被分配多于其實際需求的資源,造成資源浪費和吞吐量降低。

下面我們通過一個例子說明資源分配對SM占用率的影響。假設我們使用32個線程的線程塊,并需要總共2048個線程,那么我們將需要64個這樣的線程塊。然而,每個SM一次只能處理32個線程塊。因此,即使一個SM可以運行2048個線程,但它一次也只能同時運行1024個線程,占用率僅為50%。

同樣地,每個SM具有65536個寄存器。要同時執行2048個線程,每個線程最多有32個寄存器(65536/2048 =32)。如果一個kernel需要每個線程有64個寄存器,那么每個SM只能運行1024個線程,占用率同樣為50%。

占用率不足的挑戰在于,可能無法提供足夠的時延容忍度或所需的計算吞吐量,以達到硬件的最佳性能。

高效創建GPU kernel是一項復雜任務。我們必須合理分配資源,在保持高占用率的同時盡量降低時延。例如,擁有大量寄存器可以加快代碼的運行速度,但可能會降低占用率,因此謹慎優化代碼至關重要。

06. 總結

我理解眾多的新術語和新概念可能令讀者望而生畏,因此文章最后對要點進行了總結,以便快速回顧。

GPU由多個SM組成,每個SM又包含多個處理核心。

GPU上存在著一個片外全局內存,通常是高帶寬內存(HBM)或動態隨機存取內存(DRAM)。它與芯片上的SM相距較遠,因此時延較高。

GPU中有兩個級別的緩存:片外L2緩存和片上L1緩存。L1和L2緩存的工作方式類似于CPU中的L1/L2緩存。

每個SM上都有一小塊可配置的共享內存。這塊共享內存在處理核心之間共享。通常情況下,線程塊內的線程會將一段數據加載到共享內存中,并在需要時重復使用,而不是每次再從全局內存中加載。

每個SM都有大量寄存器,寄存器會根據線程需求進行劃分。NVIDIA H100每個SM有65536個寄存器。

在GPU上執行kernel時,我們需要啟動一個線程網格。網格由一個或多個線程塊組成,而每個線程塊又由一個或多個線程組成。

根據資源可用性,GPU會分配一個或多個線程塊在SM上執行。同一個線程塊中的所有線程都會被分配到同一個SM上執行。這樣做的目的是為了充分利用數據的局部性(data locality),并實現線程之間的同步。

被分配給SM的線程進一步分為大小為32的組,稱為warp。一個warp內的所有線程同時執行相同的指令,但在數據的不同部分上執行(SIMT)(盡管新一代GPU也支持獨立的線程調度)。

GPU根據每個線程的需求和SM的限制,在線程之間進行動態資源劃分。程序員需要仔細優化代碼,以確保在執行過程中達到最高的SM占用率。

審核編輯:湯梓紅

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

    關注

    68

    文章

    19165

    瀏覽量

    229138
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10825

    瀏覽量

    211155
  • gpu
    gpu
    +關注

    關注

    28

    文章

    4701

    瀏覽量

    128707
  • 深度學習
    +關注

    關注

    73

    文章

    5492

    瀏覽量

    120978

原文標題:GPU架構與計算入門指南

文章出處:【微信號:算力基建,微信公眾號:算力基建】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    聊聊Rust與C語言交互的具體步驟

    rust FFI 是rust與其他語言互調的橋梁,通過FFI rust 可以有效繼承 C 語言的歷史資產。本期通過幾個例子來聊聊rust與 C 語言交互的具體步驟
    發表于 07-06 11:15 ?1672次閱讀

    【「算力芯片 | 高性能 CPU/GPU/NPU 微架構分析」閱讀體驗】--了解算力芯片GPU

    每個CUDA單元 OpenCL 編程框架中都有對應的單元。 倒金字塔結構GPU存儲體系 共享內存是開發者可配置的編程資源,使用門檻較高,編程需要更多的人工顯式處理。 并行計算
    發表于 11-03 12:55

    急需求教labview實例應用具體步驟

    急需求教labview實例應用具體步驟
    發表于 12-22 00:11

    有關平衡桿小車的實驗 具體步驟

    有關平衡桿小車的實驗具體步驟
    發表于 07-18 15:11

    CPUGPU擅長和不擅長的地方

    和不擅長”。 芯片的速度主要取決于三個方面:微架構、主頻、IPC(每個時鐘周期執行的指令數)。 1.微架構從微架構看,
    發表于 12-03 15:43

    CPUGPU擅長和不擅長的地方

    和不擅長”。芯片的速度主要取決于三個方面:微架構、主頻、IPC(每個時鐘周期執行的指令數)。1.微架構從微架構看,
    發表于 12-03 20:08

    請問ucos51移植建立工程的具體步驟是什么?

    大神門,俺是新手,ucos251的移植時具體步驟是什么,包括建立工程啊等等
    發表于 05-20 00:21

    請問UCGUI中移植觸摸的具體步驟是什么?

    請教各位一下UCGUI中移植觸摸的具體步驟是什么?我現在能讀出按下時的AD值把GUI_TOUCH_Exec()放在主任務中10ms掃描一次調用了 GUI_CURSOR_Show();函數宏定義中
    發表于 07-17 04:35

    請問matlab生成TMS C6747可執行的代碼具體步驟是什么?

    請問 matlab 生成 TMS C6747可執行的代碼具體步驟 是什么??具體應該怎么設置 real_time workshop??謝謝
    發表于 07-27 07:16

    STM32新建工程具體步驟

    具體步驟:1、桌面新建一文件夾,命名為“formal-study1”2、文件夾中新建子文件夾如下圖:上圖個文件的作用:Project:用來存放工程Libraries:用來存放固件庫User:自己
    發表于 08-24 07:21

    LiteOSRISC-V架構的適配過程的具體步驟有哪些

    RISC-V是什么?LiteOSRISC-V架構的適配過程的具體步驟有哪些?
    發表于 10-19 10:23

    GPUCPU間的比較

    GPUCPU比較GPU為什么更適合深度學習?
    的頭像 發表于 08-26 15:32 ?4659次閱讀

    MAVLink學習之路04_MAVLink移植到STM32具體步驟

    MAVLink學習之路04_MAVLink移植到STM32具體步驟(提供源代碼)
    的頭像 發表于 03-07 16:22 ?4437次閱讀

    蘋果智能手機點膠的具體步驟及資料

    蘋果智能手機點膠的具體步驟及資料
    發表于 03-21 11:44 ?33次下載
    蘋果智能手機點膠的<b class='flag-5'>具體步驟</b>及資料

    西門子V20變頻器PID控制恒壓供水的具體步驟

    西門子V20變頻器PID控制恒壓供水的具體步驟 具體步驟可參考如下 : 硬件接線西門子基本型變頻器 SINAMICS V20 可應用于恒壓供水系統,本文提供具體的接線及簡單操作流程。通過BOP設置
    發表于 04-10 09:49 ?7次下載
    西門子V20變頻器PID控制恒壓供水的<b class='flag-5'>具體步驟</b>