同設(shè)計:從架構(gòu)到落地的全鏈路實踐)
1. AI芯片軟硬件協(xié)同設(shè)計的整體思路拆解1.1 為什么軟硬件必須一起設(shè)計做AI芯片這行的人都有一個共識硬件性能再強如果軟件棧跟不上實際跑出來的吞吐量可能連理論峰值的30%都不到。我見過太多團隊流片回來發(fā)現(xiàn)算子覆蓋率不夠、調(diào)度器效率低下、內(nèi)存帶寬利用率上不去最后只能靠降頻或者砍模型來湊合上線。這不是硬件設(shè)計的問題也不是軟件偷懶而是兩者從一開始就沒有放在同一張桌子上討論。軟硬件協(xié)同設(shè)計的核心邏輯其實很樸素AI負載的計算模式跟傳統(tǒng)通用計算完全不同。傳統(tǒng)CPU處理的是分支密集、訪存隨機的邏輯而AI推理和訓練的核心是大規(guī)模矩陣乘加、卷積、歸一化這些規(guī)則但計算量爆炸的操作。這意味著硬件的數(shù)據(jù)通路、緩存層級、指令集設(shè)計都必須圍繞這些操作來定制而軟件則需要在編譯、調(diào)度、內(nèi)存分配層面主動配合硬件的物理約束。我個人的經(jīng)驗是一個AI芯片項目在架構(gòu)定義階段就應(yīng)該讓編譯器團隊和runtime團隊深度參與。比如如果硬件決定了PE陣列是128x128的脈動結(jié)構(gòu)那編譯器就必須知道數(shù)據(jù)以什么粒度、什么順序流入才能打滿陣列。如果等到RTL凍結(jié)了再讓軟件團隊去適配那基本就是拿著錘子找釘子怎么擰都別扭。1.2 從應(yīng)用場景反推硬件規(guī)格很多團隊做芯片喜歡先定一個“大而全”的目標比如支持所有主流算子、兼容所有框架。但實際落地時你會發(fā)現(xiàn)真正決定芯片競爭力的往往是對兩三個核心場景的極致優(yōu)化。我參與過一個邊緣推理芯片的項目最初想同時覆蓋檢測、分割、分類三大類模型結(jié)果面積和功耗都爆了。后來砍掉分割專注優(yōu)化卷積和矩陣乘反而在目標場景下做到了能效比領(lǐng)先。反推的邏輯鏈條是這樣的先確定目標模型的計算圖特征統(tǒng)計各類算子的調(diào)用頻次和耗時占比然后針對Top 5算子設(shè)計專用加速單元剩下的用可編程核兜底。這個過程需要軟件團隊提供真實的profiling數(shù)據(jù)而不是拍腦袋估計。我通常建議用三到五個代表性模型做端到端分析把每一層的延遲、帶寬需求、并行度都列出來形成一張“算子-硬件資源映射表”。1.3 軟硬件接口的抽象層級選擇接口抽象層級是個很容易踩坑的地方。抽象太高硬件細節(jié)被隱藏編譯器無法做精細優(yōu)化抽象太低軟件團隊要直接面對寄存器操作開發(fā)效率極低且容易出錯。我的經(jīng)驗是采用兩層抽象底層是硬件指令集和內(nèi)存模型供編譯器后端做指令選擇和寄存器分配上層是算子庫和運行時API供框架集成和用戶調(diào)用。具體來說硬件指令集需要暴露足夠的信息讓編譯器做調(diào)度決策比如DMA的通道數(shù)、PE陣列的配置模式、片上緩存的bank劃分。但不需要暴露具體的時序細節(jié)那些由硬件自動處理。算子庫則封裝常用的卷積、矩陣乘、激活函數(shù)等提供與框架對接的標準接口。這樣既保證了優(yōu)化空間又控制了軟件復雜度。2. 核心模塊的硬件設(shè)計細節(jié)與實操要點2.1 計算陣列的微架構(gòu)選擇計算陣列是AI芯片的心臟常見的結(jié)構(gòu)有脈動陣列、SIMD/SIMT、以及粗粒度可重構(gòu)陣列。脈動陣列的優(yōu)勢是數(shù)據(jù)復用率高、控制邏輯簡單適合規(guī)則的大矩陣運算缺點是靈活性差遇到非規(guī)則計算容易閑置。SIMT則更通用但面積和功耗開銷大。我在實際項目中傾向于混合方案主計算陣列用脈動結(jié)構(gòu)處理卷積和全連接輔以一個小的向量單元處理激活、池化等逐元素操作。這樣既保證了主算力的效率又避免了為每個小算子單獨設(shè)計硬件的浪費。關(guān)鍵參數(shù)包括陣列維度、數(shù)據(jù)位寬、累加器精度。以128x128的INT8陣列為例每個周期可以完成16384次乘加如果頻率跑到1GHz理論算力就是32TOPS。但實際有效算力取決于數(shù)據(jù)供給能否跟上所以片上緩存帶寬必須匹配。注意陣列維度不是越大越好。維度增大意味著布線延遲增加、時鐘樹更難平衡而且小模型可能根本填不滿陣列。我見過256x256的陣列在跑小模型時利用率不到20%純屬浪費面積。2.2 片上內(nèi)存層級的設(shè)計取舍AI芯片的瓶頸往往不在算力而在內(nèi)存帶寬。片上內(nèi)存的設(shè)計需要在容量、帶寬、面積、功耗之間做權(quán)衡。常見的層級是寄存器文件、L1緩存/暫存器、L2緩存、以及外部DRAM接口。我的做法是把L1暫存器設(shè)計成可配置的bank結(jié)構(gòu)每個bank獨立尋址支持多端口并發(fā)訪問。這樣編譯器可以根據(jù)算子的數(shù)據(jù)復用模式把輸入特征圖、權(quán)重、輸出分別放在不同的bank里避免訪問沖突。L2緩存則采用統(tǒng)一編址負責在L1和DRAM之間做數(shù)據(jù)搬運和復用。一個具體的參數(shù)計算例子假設(shè)目標模型的最大單層卷積需要同時駐留64KB輸入、32KB權(quán)重、64KB輸出那么L1總?cè)萘恐辽?60KB??紤]到雙緩沖和預(yù)取實際設(shè)計成256KB比較穩(wěn)妥。帶寬方面如果計算陣列每周期需要256字節(jié)的輸入數(shù)據(jù)L1的讀帶寬就必須達到256字節(jié)/周期這通常需要4個64字節(jié)寬的bank并行工作。2.3 數(shù)據(jù)流控制與DMA設(shè)計數(shù)據(jù)搬運的效率直接決定了計算單元的利用率。DMA的設(shè)計要點包括多通道支持、描述符鏈式調(diào)度、以及與計算單元的同步機制。我通常設(shè)計至少4個DMA通道分別負責輸入特征、權(quán)重、輸出結(jié)果、以及中間數(shù)據(jù)的搬運。描述符鏈式調(diào)度是個很實用的技巧把一系列搬運任務(wù)組織成鏈表DMA自動按順序執(zhí)行完成一個后通過中斷或信號量通知計算單元。這樣CPU或調(diào)度器不需要頻繁干預(yù)減少了控制開銷。同步機制方面我傾向于用硬件信號量而不是中斷因為中斷延遲大且會打斷流水線。實操心得DMA的burst長度要跟DRAM的頁大小匹配。如果burst太短DRAM頻繁換頁有效帶寬會掉一半。一般設(shè)成64或128字節(jié)比較合適具體要看DRAM控制器的參數(shù)。2.4 指令集與編譯器后端協(xié)同指令集設(shè)計不是硬件團隊閉門造車必須和編譯器團隊一起定。我參與的項目里指令集通常包含以下幾類計算指令矩陣乘、卷積、向量運算、數(shù)據(jù)搬運指令DMA配置、緩存預(yù)取、控制指令循環(huán)、分支、同步、以及配置指令設(shè)置陣列模式、精度模式。編譯器后端需要做指令選擇、寄存器分配、指令調(diào)度。其中指令調(diào)度對性能影響最大因為AI計算的數(shù)據(jù)依賴關(guān)系復雜調(diào)度不好就會產(chǎn)生流水線氣泡。我的經(jīng)驗是讓編譯器支持軟件流水把循環(huán)展開后重新排列指令順序讓DMA搬運和計算重疊起來。這需要硬件提供足夠的寄存器資源和異步執(zhí)行單元。3. 軟件棧的實現(xiàn)與優(yōu)化實操3.1 編譯器前端的圖優(yōu)化編譯器前端負責把框架導出的計算圖轉(zhuǎn)換成中間表示然后做一系列圖級別的優(yōu)化。常見的優(yōu)化包括算子融合、常量折疊、死代碼消除、內(nèi)存布局轉(zhuǎn)換。其中算子融合對AI芯片特別重要因為把卷積、BN、激活融合成一個算子可以減少中間結(jié)果的寫回和讀取節(jié)省大量帶寬。我通常會在前端做三輪優(yōu)化第一輪是通用優(yōu)化跟硬件無關(guān)第二輪是硬件感知優(yōu)化比如根據(jù)陣列大小決定tile尺寸第三輪是內(nèi)存分配優(yōu)化把生命周期不重疊的張量分配到同一塊內(nèi)存。三輪下來一個典型的ResNet50可以縮減30%以上的內(nèi)存訪問量。3.2 算子庫的手寫優(yōu)化技巧雖然編譯器能自動生成代碼但核心算子還是需要手寫匯編或內(nèi)聯(lián)函數(shù)來榨取最后一點性能。手寫算子的關(guān)鍵是理解硬件的微架構(gòu)細節(jié)PE陣列的流水線深度、寄存器的讀寫端口沖突、DMA的啟動延遲等。以卷積為例我通常采用im2col加矩陣乘的方式但會針對硬件做定制。比如如果陣列是脈動結(jié)構(gòu)就把im2col的展開順序調(diào)整成跟脈動方向一致讓數(shù)據(jù)自然流動。如果L1暫存器有bank沖突就調(diào)整數(shù)據(jù)布局把頻繁同時訪問的數(shù)據(jù)放到不同bank。這些技巧編譯器很難自動發(fā)現(xiàn)需要人工介入。注意手寫算子雖然性能好但維護成本高。我的建議是只對Top 10熱點算子手寫其余用編譯器生成。而且手寫算子要有完整的測試用例確保數(shù)值正確性和邊界情況覆蓋。3.3 運行時調(diào)度與內(nèi)存管理運行時負責把編譯好的算子按依賴關(guān)系調(diào)度到硬件上執(zhí)行同時管理內(nèi)存分配和釋放。調(diào)度策略有靜態(tài)和動態(tài)兩種靜態(tài)調(diào)度在編譯時確定執(zhí)行順序開銷小但靈活性差動態(tài)調(diào)度在運行時根據(jù)資源狀態(tài)決定靈活但開銷大。我傾向于混合策略主計算圖用靜態(tài)調(diào)度保證確定性動態(tài)shape或條件分支用動態(tài)調(diào)度兜底。內(nèi)存管理方面采用內(nèi)存池加引用計數(shù)的方式避免頻繁的malloc/free。內(nèi)存池按大小分級小對象從固定塊分配大對象單獨管理。3.4 框架對接與用戶接口用戶不會直接調(diào)用算子庫他們用的是PyTorch、TensorFlow這些框架。所以需要提供一個橋接層把框架的算子映射到自家芯片的算子庫。這個橋接層通常包括圖解析、算子映射、內(nèi)存拷貝、以及執(zhí)行引擎。圖解析負責把框架的IR轉(zhuǎn)換成自家IR算子映射負責找到對應(yīng)的硬件算子找不到的就用CPU fallback內(nèi)存拷貝負責在Host和Device之間搬數(shù)據(jù)執(zhí)行引擎負責按順序調(diào)用算子。這個橋接層的性能也很關(guān)鍵如果每次推理都要做大量Host-Device拷貝端到端延遲會很難看。4. 常見問題與排查技巧實錄4.1 性能不達預(yù)期的排查思路性能問題是最常見的排查起來也最耗時。我的排查順序是先看計算單元利用率再看內(nèi)存帶寬利用率最后看DMA和同步開銷。如果計算利用率低可能是數(shù)據(jù)供給不足或者陣列配置不對如果帶寬利用率高但計算利用率低可能是數(shù)據(jù)復用沒做好如果兩者都不高可能是同步或調(diào)度開銷太大。具體工具方面我會在硬件里埋性能計數(shù)器統(tǒng)計每個模塊的活躍周期、 stall周期、以及各類事件的次數(shù)。軟件側(cè)則用profiling工具記錄每個算子的耗時和內(nèi)存訪問量。兩邊數(shù)據(jù)一對基本就能定位瓶頸。4.2 數(shù)值精度問題的定位與解決AI芯片通常支持INT8、FP16、甚至FP8不同精度下的數(shù)值行為差異很大。常見問題包括溢出、舍入誤差累積、以及非對稱量化導致的偏差。我遇到過一次INT8推理精度掉點嚴重的情況最后發(fā)現(xiàn)是激活函數(shù)的量化參數(shù)在某個通道上估計不準導致大量值被截斷。解決思路是先做逐層對比找到誤差最大的層然后檢查該層的量化參數(shù)是否合理最后調(diào)整量化策略比如改用對稱量化或者增加校準數(shù)據(jù)。硬件層面累加器位寬要足夠INT8乘加通常需要32位累加器否則多層累加后會溢出。4.3 軟硬件版本不匹配的坑這個坑很隱蔽但很致命。硬件流片后可能有ECO或者metal fix導致寄存器地址或行為跟設(shè)計文檔不一致。軟件如果按舊文檔寫就會出現(xiàn)莫名其妙的錯誤。我的做法是維護一個硬件版本寄存器軟件啟動時讀取并校驗不匹配就報錯退出。同時硬件團隊每次改版都要提供變更說明軟件團隊據(jù)此更新驅(qū)動和算子庫。4.4 常見問題速查表問題現(xiàn)象可能原因排查方法解決措施計算利用率低于50%數(shù)據(jù)供給不足檢查DMA帶寬和L1命中率增大預(yù)取深度優(yōu)化數(shù)據(jù)布局推理結(jié)果偏差大量化參數(shù)不準逐層對比浮點和定點輸出重新校準調(diào)整量化策略運行時報內(nèi)存錯誤內(nèi)存池碎片或越界開啟內(nèi)存檢查打印分配日志調(diào)整池大小修復越界訪問端到端延遲高Host-Device拷貝多統(tǒng)計拷貝次數(shù)和數(shù)據(jù)量合并拷貝使用零拷貝接口多核并行效率低同步開銷大測量同步等待時間改用無鎖隊列或硬件信號量實操心得每次流片回來我都會先跑一個“冒煙測試”套件覆蓋所有算子和典型模型。這個套件在仿真階段就要準備好流片后直接跑能快速發(fā)現(xiàn)硬件bug。另外保留一份“黃金數(shù)據(jù)”即已知正確的輸入輸出對任何改動后都跑一遍對比確保數(shù)值一致性。4.5 功耗與散熱的實測經(jīng)驗功耗問題在邊緣設(shè)備上尤其突出。我遇到過芯片跑滿時功耗超標導致降頻甚至死機。排查后發(fā)現(xiàn)是時鐘樹功耗和漏電功耗占比過高。解決方法是在軟件層面做動態(tài)電壓頻率調(diào)節(jié)根據(jù)負載調(diào)整頻率在硬件層面優(yōu)化時鐘門控空閑模塊及時關(guān)斷。散熱方面邊緣設(shè)備通常沒有風扇全靠被動散熱。所以芯片的布局要考慮熱源分散避免局部過熱。軟件上可以監(jiān)控溫度傳感器超過閾值就降頻。實測下來把峰值功耗控制在熱設(shè)計功耗的80%以內(nèi)基本能保證長時間穩(wěn)定運行。5. 從項目實踐中沉淀的經(jīng)驗5.1 仿真驗證的重要性流片一次成本極高所以仿真驗證必須做充分。我通常分三個階段單元級驗證、子系統(tǒng)級驗證、以及全芯片級驗證。單元級用定向測試和隨機測試覆蓋各種邊界情況子系統(tǒng)級跑真實算子對比參考模型全芯片級跑完整模型統(tǒng)計性能和精度。仿真平臺的選擇也很關(guān)鍵。RTL仿真慢但準確適合最終驗證FPGA原型快但可能有時序差異適合早期軟件開發(fā)還有基于C模型的虛擬平臺速度最快但精度最低適合架構(gòu)探索。我的建議是三者結(jié)合早期用虛擬平臺快速迭代中期用FPGA跑軟件棧后期用RTL做最終確認。5.2 軟件先行策略硬件還沒回來軟件團隊不能干等。我的做法是先基于虛擬平臺或FPGA原型開發(fā)軟件棧把編譯器、算子庫、運行時都跑通。等硬件回來只需要做適配和調(diào)優(yōu)而不是從零開始。這樣能節(jié)省至少三個月的時間。軟件先行還有個好處能提前發(fā)現(xiàn)硬件設(shè)計的缺陷。比如編譯器團隊發(fā)現(xiàn)某個算子無法高效映射反饋給硬件團隊可能只需要改一點微架構(gòu)就能解決。如果等流片后再發(fā)現(xiàn)那就只能軟件繞路性能損失很大。5.3 持續(xù)集成與回歸測試AI芯片的軟硬件都在快速迭代沒有持續(xù)集成很容易亂套。我建議搭建一套CI系統(tǒng)每次代碼提交都自動編譯、跑測試、出報告。測試集要覆蓋算子正確性、模型精度、性能回歸、以及穩(wěn)定性。性能回歸特別重要因為優(yōu)化一個算子可能拖慢另一個沒有回歸測試根本發(fā)現(xiàn)不了。回歸測試的基線要定期更新但不能太頻繁否則噪音太大。我通常每周更新一次基線每次更新前人工確認性能變化是預(yù)期的。另外測試環(huán)境要統(tǒng)一包括硬件版本、驅(qū)動版本、編譯器版本否則結(jié)果不可比。5.4 與算法團隊的協(xié)作模式算法團隊和芯片團隊的目標不完全一致算法追求精度和創(chuàng)新芯片追求效率和通用性。協(xié)作的關(guān)鍵是找到平衡點。我的經(jīng)驗是算法團隊在模型設(shè)計階段就要考慮硬件約束比如避免使用硬件不支持的算子控制模型規(guī)模在芯片內(nèi)存范圍內(nèi)。芯片團隊則要提供易用的工具鏈讓算法團隊能快速評估模型在芯片上的性能。具體做法是建立一個聯(lián)合評審機制算法團隊每提出一個新模型芯片團隊就評估其硬件友好度給出優(yōu)化建議。反過來芯片團隊每改一版架構(gòu)算法團隊就評估對現(xiàn)有模型的影響。這樣雙方都能提前發(fā)現(xiàn)問題避免后期返工。5.5 文檔與知識沉淀芯片項目的周期長、參與人多文檔如果跟不上后面維護會非常痛苦。我要求團隊做到每個模塊有設(shè)計文檔每個接口有規(guī)格說明每個bug有分析報告。文檔不是寫完就完了要隨著代碼更新而更新。我見過太多項目代碼改了文檔沒改后來的人照著舊文檔操作踩了一堆坑。知識沉淀方面我建議定期做技術(shù)分享讓不同模塊的同事了解彼此的工作。這樣遇到跨模塊問題時能快速找到相關(guān)人。另外建立一個“坑庫”記錄項目中遇到的所有問題和解決方法新人入職先讀這個能少走很多彎路。5.6 流片后的bring-up流程芯片回來后的bring-up是最緊張的階段。我的流程是先檢查電源和時鐘確保芯片能正常上電然后跑JTAG測試確認掃描鏈正常接著加載簡單的測試程序驗證CPU核和內(nèi)存最后逐步加載復雜程序測試各個加速單元。Bring-up過程中最容易出問題的是時鐘和復位。我遇到過復位信號毛刺導致芯片隨機死機的情況排查了很久才發(fā)現(xiàn)是復位樹的布線問題。所以bring-up階段要準備充分的調(diào)試手段比如片上邏輯分析儀、可配置的測試寄存器等。5.7 量產(chǎn)前的最終驗證量產(chǎn)前的驗證要覆蓋功能、性能、功耗、可靠性、以及兼容性。功能方面跑完整的模型庫和測試集性能方面統(tǒng)計不同負載下的吞吐量和延遲功耗方面測量典型場景和峰值場景的功耗可靠性方面做高低溫循環(huán)和長時間老化測試兼容性方面驗證與主流框架和操作系統(tǒng)的對接。這個階段發(fā)現(xiàn)的問題修復成本極高所以前面的驗證越充分越好。我的經(jīng)驗是量產(chǎn)前至少留出兩個月做最終驗證不要壓縮這個時間。一旦量產(chǎn)發(fā)現(xiàn)問題召回的成本可能是驗證成本的幾十倍。5.8 后續(xù)演進的方向思考AI芯片的軟硬件設(shè)計不是一錘子買賣需要持續(xù)演進。硬件方面可以通過增加陣列規(guī)模、提升內(nèi)存帶寬、支持新精度來提升性能軟件方面可以通過優(yōu)化編譯器、豐富算子庫、改進調(diào)度策略來挖掘潛力。關(guān)鍵是保持軟硬件的同步迭代不要出現(xiàn)硬件等軟件或者軟件等硬件的情況。另外要關(guān)注算法的發(fā)展趨勢。比如Transformer架構(gòu)的普及對芯片提出了新的要求更大的片上內(nèi)存、更靈活的注意力計算、以及更好的稀疏支持。如果硬件設(shè)計不考慮這些趨勢可能兩年后就落后了。所以架構(gòu)設(shè)計要有一定的前瞻性預(yù)留擴展空間。我個人在實際操作中的體會是AI芯片項目成功的關(guān)鍵不在于單點技術(shù)有多先進而在于軟硬件團隊能否緊密協(xié)作、快速迭代。我見過技術(shù)很牛的團隊因為協(xié)作不暢而失敗也見過技術(shù)一般的團隊因為配合默契而做出可用的產(chǎn)品。所以如果你正在做類似的項目建議把至少30%的精力放在團隊協(xié)作和流程建設(shè)上這比單純優(yōu)化一個算子帶來的收益大得多。