最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【2023 · CANN訓(xùn)練營第一季】課堂筆記2-算子編程范式及算子實(shí)現(xiàn)

2023-05-30 12:49 作者:白子不擺爛版  | 我要投稿

【2023 · CANN訓(xùn)練營第一季】課堂筆記2-算子編程范式及算子實(shí)現(xiàn)

一、算子編程范式

1.簡介:

  • 快速開發(fā)編程的固定步驟

  • 統(tǒng)一代碼框架的開發(fā)捷徑

  • 使用者總結(jié)出的開發(fā)經(jīng)驗(yàn)

  • 面向特定場景的編程思想

  • 定制化的方法論開發(fā)體驗(yàn)

TIK C++編程范式把算子內(nèi)部的處理程序,分成多個(gè)流水任務(wù)(Stage),以張量(Tensor)為數(shù)據(jù)載體,以隊(duì)列(Queue)進(jìn)行任務(wù)之間的通信與同步,以內(nèi)存管理模塊(Pipe)管理任務(wù)間的通信內(nèi)存。

2.流水任務(wù):

流水任務(wù)(Stage)指的是單核處理程序中主程序調(diào)度的并行任務(wù)。在核函數(shù)內(nèi)部,可以通過流水任務(wù)實(shí)現(xiàn)數(shù)據(jù)的并行處理來提升性能。

單核處理程序的功能可以被拆分成3個(gè)流水任務(wù):Stage1、Stage2、Stage3,每個(gè)任務(wù)專注于完成單一功能;需要處理的數(shù)據(jù)被切分成n片,使用Progress1~n表示,每個(gè)任務(wù)需要依次完成n個(gè)數(shù)據(jù)切片的處理。Stage間的箭頭表達(dá)數(shù)據(jù)間的依賴關(guān)系,比如Stage1處理完P(guān)rogress1之后,Stage2才能對Progress1進(jìn)行處理

若Progress的n=3,待處理的數(shù)據(jù)被切分成3片,對于同一片數(shù)據(jù),Stage1、Stage2、Stage3之間的處理具有依賴關(guān)系,需要串行處理;不同的數(shù)據(jù)切片,同一時(shí)間點(diǎn),可以有多個(gè)流水任務(wù)Stage在并行處理,由此達(dá)到任務(wù)并行、提升性能的目的

流水的三大基本任務(wù): CopyIn:負(fù)責(zé)數(shù)據(jù)搬入操作---->輸入數(shù)據(jù)從Global內(nèi)存搬移到Local內(nèi)存

Compute:負(fù)責(zé)矢量計(jì)算操作---->使用local內(nèi)存進(jìn)行計(jì)算

CopyOut:負(fù)責(zé)數(shù)據(jù)搬出操作---->輸入數(shù)據(jù)從Local內(nèi)存搬移到Global內(nèi)存

3.任務(wù)間的通信與同步:

不同的流水任務(wù)之間存在數(shù)據(jù)依賴,需要進(jìn)行數(shù)據(jù)傳遞 TIK C++中使用Queue隊(duì)列完成任務(wù)之間的數(shù)據(jù)通信和同步,Queue提供了EnQue、DeQue等基礎(chǔ)API Queue隊(duì)列管理NPU上不同層級的物理內(nèi)存時(shí),用一種抽象的邏輯位置(QuePosition)來表達(dá)各個(gè)級別的存儲(Storage Scope),代替了片上物理存儲的概念,開發(fā)者無需感知硬件架構(gòu) 矢量編程中Queue類型(邏輯位置)包括:VECIN、VECOUT

上文提到的Local內(nèi)存和Global內(nèi)存,是數(shù)據(jù)的載體,他們分別使用GlobalTensor和LocalTensor作為數(shù)據(jù)的基本操作單元,它是各種指令A(yù)PI直接調(diào)用的對象

矢量編程介紹:

矢量編程中有兩個(gè)邏輯位置(QuePosition):

搬入數(shù)據(jù)的存放位置:VECIN

搬出數(shù)據(jù)的存放位置:VECOUT

其操作也是可以按照流水任務(wù)的三個(gè)stage對應(yīng)其三個(gè)主要流水任務(wù)

  • Stage1:CopyIn任務(wù)

1.使用DataCopy接口將GlobalTensor拷貝到LocalTensor。

2.使用EnQue將LocalTensor放入VECIN的Queue中

  • Stage2:Compute任務(wù)

1.使用DeQue從VECIN中取出LocalTensor

2.使用TIK C++指令A(yù)PI完成矢量計(jì)算:Add 3.使用EnQue將結(jié)果LocalTensor放入VECOUT的Queue中

  • Stage3:CopyOut任務(wù)

1.使用DeQue接口從VECOUT的Queue中取出LocalTensor

2.使用DataCopy接口將LocalTensor拷貝到GlobalTensor

4.內(nèi)存管理

任務(wù)間數(shù)據(jù)傳遞使用到的內(nèi)存統(tǒng)一由內(nèi)存管理模塊Pipe進(jìn)行管理 Pipe作為片上內(nèi)存管理者,通過InitBuffer接口對外提供Queue內(nèi)存初始化功能,開發(fā)者可以通過該接口為指定的Queue分配內(nèi)存 Queue隊(duì)列內(nèi)存初始化完成后,需要使用內(nèi)存時(shí),通過調(diào)用AllocTensor來為LocalTensor分配內(nèi)存給Tensor,當(dāng)創(chuàng)建的LocalTensor完成相關(guān)計(jì)算無需再使用時(shí),再調(diào)用FreeTensor來回收LocalTensor的內(nèi)存

5.臨時(shí)變量的內(nèi)存管理

編程過程中使用到的臨時(shí)變量內(nèi)存同樣通過Pipe進(jìn)行管理。臨時(shí)變量可以使用TBuf數(shù)據(jù)結(jié)構(gòu)來申請指定QuePosition上的存儲空間,并使用Get()來將分配到的存儲空間分配給新的LocalTensor

從TBuf上獲取全部長度,或者獲取指定長度的LocalTensor

ps:使用TBuf申請的內(nèi)存空間只能參與計(jì)算,無法執(zhí)行Queue隊(duì)列的入隊(duì)出隊(duì)操作

二、算子開發(fā)流程--矢量算子的編程

快速TIK C++算子開發(fā)流程:

  • 完成算子核函數(shù)的開發(fā)

  • 基于內(nèi)核調(diào)用符方式進(jìn)行算子運(yùn)行驗(yàn)證

標(biāo)準(zhǔn)TIK C++算子開發(fā)流程:

  • 完成算子核函數(shù)的開發(fā)

  • 完成單算子網(wǎng)絡(luò)應(yīng)用程序的開發(fā)

  • 基于ACL單算子調(diào)用方式進(jìn)行算子運(yùn)行驗(yàn)證

標(biāo)準(zhǔn)和快速開發(fā)兩種方式的對比

三大步驟:

算子分析:分析算子的數(shù)學(xué)表達(dá)式、輸入、輸出以及計(jì)算邏輯的實(shí)現(xiàn),明確需要調(diào)用的TIK C++接口。?核函數(shù)定義:定義TIK C++算子入口函數(shù)。?根據(jù)矢量編程范式實(shí)現(xiàn)算子類:完成核函數(shù)的內(nèi)部實(shí)現(xiàn)。

(1)算子分析:

  • 明確算子的數(shù)學(xué)表達(dá)式及計(jì)算邏輯

  • 明確輸入和輸出

  • 確定核函數(shù)名稱和參數(shù)

  • 確定算子實(shí)現(xiàn)所需接口

(2)核函數(shù)定義:

1.完成內(nèi)存初始化:

2.完成核心邏輯實(shí)現(xiàn)

3.對于核函數(shù)的調(diào)用,使用內(nèi)置宏__CCE_KT_TEST__來標(biāo)識<<<…>>>僅在NPU模式下才會編譯到(CPU模式g++沒有<<<…>>>的表達(dá)),對核函數(shù)的調(diào)用進(jìn)行封裝,

(3)算子類的實(shí)現(xiàn)

流水任務(wù):

  • CopyIn任務(wù):將Global Memory上的輸入Tensor xGm和yGm搬運(yùn)至Local Memory,分別存儲在xLocal, yLocal

  • Compute任務(wù):對xLocal, yLocal執(zhí)行加法操作,計(jì)算結(jié)果存儲在zLocal中

  • CopyOut任務(wù):將輸出數(shù)據(jù)從zLocal搬運(yùn)至Global Memory上的輸出Tensor zGm中

各任務(wù)的通信方式:

  • CopyIn,Compute任務(wù)間通過VECIN隊(duì)列inQueueX,inQueueY進(jìn)行通信和同步

  • Compute,CopyOut任務(wù)間通過VECOUT隊(duì)列outQueueZ進(jìn)行通信和同步

pipe內(nèi)存管理對象對任務(wù)間交互使用到的內(nèi)存、臨時(shí)變量使用到的內(nèi)存統(tǒng)一進(jìn)行管理

Init函數(shù)的實(shí)現(xiàn)

這里老師講解的例子是一個(gè)add算子,shape是(8,2048)的,打算將其放入8個(gè)核進(jìn)行計(jì)算,這里老師的init代碼如下:

使用多核并行計(jì)算的方法:

需要將數(shù)據(jù)切片,獲取到每個(gè)核實(shí)際需要處理的在Global Memory上的內(nèi)存偏移地址 數(shù)據(jù)整體長度TOTAL_LENGTH為8* 2048,平均分配到8個(gè)核上運(yùn)行,每個(gè)核上處理的數(shù)據(jù)大小BLOCK_LENGTH為2048。block_idx為核的邏輯ID,(gm?half*)x + block_idx * BLOCK_LENGTH即索引為block_idx的核的輸入數(shù)據(jù)在Global Memory上的內(nèi)存偏移地址

使用單核處理數(shù)據(jù)的方法:

可以進(jìn)行數(shù)據(jù)切塊(Tiling),將數(shù)據(jù)切分成8塊。切分后的每個(gè)數(shù)據(jù)塊再次切分成BUFFER_NUM=2塊,可開啟double buffer,實(shí)現(xiàn)流水線之間的并行 單核需要處理的2048個(gè)數(shù)被切分成16塊,每塊TILE_LENGTH=128個(gè)數(shù)據(jù)。Pipe為inQueueX分配了BUFFER_NUM塊大小為TILE_LENGTH * sizeof(half)個(gè)字節(jié)的內(nèi)存塊,每個(gè)內(nèi)存塊能容納TILE_LENGTH=128個(gè)half類型數(shù)據(jù)

Process()函數(shù)實(shí)現(xiàn)

處理函數(shù)的實(shí)現(xiàn)主要就是三大流水任務(wù):

copyIn:

Compute:

copyOut:

double buffer機(jī)制

double buffer通過將數(shù)據(jù)搬運(yùn)與矢量計(jì)算并行執(zhí)行以隱藏?cái)?shù)據(jù)搬運(yùn)時(shí)間并降低矢量指令的等待時(shí)間,最終提高矢量計(jì)算單元的利用效率 1個(gè)Tensor同一時(shí)間只能進(jìn)行搬入、計(jì)算和搬出三個(gè)流水任務(wù)中的一個(gè),其他兩個(gè)流水任務(wù)涉及的硬件單元?jiǎng)t處于Idle狀態(tài) 如果將待處理的數(shù)據(jù)一分為二,比如Tensor1、Tensor2

  • 當(dāng)矢量計(jì)算單元對Tensor1進(jìn)行Compute時(shí),Tensor2可以執(zhí)行CopyIn的任務(wù)

  • 當(dāng)矢量計(jì)算單元對Tensor2進(jìn)行Compute時(shí),Tensor1可以執(zhí)行CopyOut的任務(wù)

  • 當(dāng)矢量計(jì)算單元對Tensor2進(jìn)行CopyOut時(shí),Tensor1可以執(zhí)行CopyIn的任務(wù)

由此,數(shù)據(jù)的進(jìn)出搬運(yùn)和矢量計(jì)算之間實(shí)現(xiàn)并行,硬件單元閑置問題得以有效緩解

ps:該文僅是為了記錄CANN訓(xùn)練營的學(xué)習(xí)過程所用,不參與任何商業(yè)用途


【2023 · CANN訓(xùn)練營第一季】課堂筆記2-算子編程范式及算子實(shí)現(xiàn)的評論 (共 條)

分享到微博請遵守國家法律
钟山县| 宜兰市| 新乡市| 封开县| 西乡县| 孙吴县| 法库县| 华亭县| 托克托县| 呼图壁县| 钟山县| 汉源县| 绵竹市| 岳阳市| 海门市| 安达市| 长兴县| 中方县| 澎湖县| 波密县| 南丹县| 读书| 肇州县| 太保市| 逊克县| 吉木萨尔县| 邻水| 原阳县| 腾冲县| 德州市| 静安区| 大洼县| 福清市| 茶陵县| 连州市| 阿拉善盟| 叙永县| 华容县| 重庆市| 西昌市| 辽宁省|