我要准备给领导讲 ccec (华为 NPU 编译器,基于 llvm)实现结构 (1)代码结构...
बनाया गया: 16 अगस्त 2026
का उपयोग करके उत्तर दिया गया GPT-5.6 Thinking द्वारा Chat01
बनाया गया: 16 अगस्त 2026
का उपयोग करके उत्तर दिया गया GPT-5.6 Thinking द्वारा Chat01
我要准备给领导讲 ccec (华为 NPU 编译器,基于 llvm)实现结构
(1)代码结构
(2)ccec特性能力
(3)多代际支持
应该具体需要哪些方面?只有一天半时间读代码+准备
可以把范围压得很明确:一天半不要试图理解所有 Pass 和所有 NPU 指令,而是围绕“一个编译流程 + 三个架构问题”读代码。
从公开资料看,CCEC 即 CCE Compiler;较新的 CANN 文档中,毕昇编译器仍安装在 compiler/ccec_compiler 下,编译工具链还包含 lld、cce-ld、llvm-objdump、llvm-ar 等。当前公开接口也明确存在 --npu-arch / --npu-soc 这样的架构选择机制。(Hiascend)
所以你的汇报完全可以按 “LLVM 主干框架 + CCE/NPU 定制 + 多架构适配层” 这条主线来组织。
1. CCEC 在整个软件栈里是什么位置?
先用一张图讲清:
textAscend C / CCE / intrinsic / builtin │ ▼ Clang Frontend │ LLVM IR │ ┌─────────┴─────────┐ │ CCE/NPU IR Passes │ │ LLVM Common Pass │ └─────────┬─────────┘ │ NPU Backend │ ISel / RegAlloc / Schedule │ MC / Asm │ Object / Device Bin │ Link / FatObj │ Runtime
不要一上来讲目录。领导首先应该知道:
CCEC 接收什么,做了什么,输出什么,与 Runtime、算子编程语言、硬件分别是什么关系。
公开文档也能看到 CCE/Ascend C 支持 AI Core device code 以及 host/device 异构编译模式。(Hiascend)
这是你第一重点。
建议最终总结成下面 5 层,然后把真实代码目录填进去。
| 层 | 你需要找什么 | 汇报时讲什么 |
|---|---|---|
| Driver / Frontend | ccec/bisheng driver、参数解析、语言扩展、builtin/intrinsic | CCE 如何进入 LLVM |
| LLVM IR / Middle-end | CCE 自定义 Pass、canonicalize、优化 | 哪些复用 LLVM,哪些 NPU 特有 |
| Target Backend | TargetMachine、Subtarget、ISel、InstrInfo、RegisterInfo | LLVM IR 如何变 NPU 指令 |
| Architecture Adaptation | arch/soc/features、CPU/Feature 判断 | 多代 NPU 如何共用一套代码 |
| MC/Link/Object | MC、object、metadata、lld/cce-ld/fatobj | 最终 device binary 怎么出来 |
尤其是 Backend 建议重点看 6 个 LLVM 经典入口:
textTargetMachine Subtarget TargetLowering InstrInfo RegisterInfo FrameLowering
再加:
textTableGen / *.td Pass pipeline Builtin / Intrinsic definition
你不是要读懂实现,而是回答:
“这个模块负责什么?上游输入是什么?下游输出是什么?”
每个模块能说一句话,就够汇报了。
这部分很容易陷进去。
建议按照用户能感知到的能力讲。
比如你代码里实际存在的:
公开编译选项里也能看到 AI Core、Vector/Cube 以及 CCE/Ascend C 等编译概念。(Hiascend)
重点找 NPU 特有的,而不是 LLVM 自带的:
textvector / cube lowering memory access DMA / data movement pipeline sync/barrier instruction combine loop address transformation
如果时间紧,只挑 2~3 个最有代表性的 Pass。
对每个 Pass 只回答:
text解决什么硬件问题 ↓ 识别什么 IR ↓ 做什么 transformation ↓ 最终得到什么收益
领导通常不会需要你逐行解释算法。
这里体现“这是个真正的 NPU compiler backend”:
这个经常被忽略,但很好讲:
-O0/-O2/-O3这些能力在当前公开编译器文档中都有对应选项或工具。(Hiascend)
这样你的“特性能力”不会变成 feature list,而是:
语言 → 优化 → 后端 → 工程化
如果领导是技术领导,我会把这里当成你的亮点。
不要只说:
支持 Ascend xxx / xxx / xxx。
这意义不大。
真正应该回答的是:
同一个 CCEC 如何同时支持不同 NPU ISA/微架构?
建议沿着下面这条链找代码:
text--npu-arch / --npu-soc │ ▼ Arch / CPU / Feature Parsing │ ▼ Subtarget / | \ FeatureA FeatureB FeatureC │ │ ├───────┤ ▼ IR Lowering / Intrinsic │ ▼ Instruction Selection │ ▼ Scheduling / Hazard │ ▼ Binary
公开接口已经明确把**产品型号 (--npu-soc)和NPU architecture (--npu-arch)**区分开,这恰好可以作为你读多代支持代码的入口。(Hiascend)
你重点找下面 7 类差异点:
ISA 差异
哪些指令只有新架构有?
Feature capability
有没有类似:
cpphasXXX() isArchXXX() FeatureXXX
Intrinsic / builtin 差异
同一个 API 在不同代际是不是 lower 成不同指令?
数据类型差异
FP16 / BF16 / INT8 / 新 datatype 谁支持?
memory hierarchy 差异
buffer/address space/cache/DMA 是否变化?
schedule / pipeline 差异
同样 ISA,微架构 latency/resource 是否不同?
ABI / binary 差异
object metadata、link、kernel metadata 有没有代际信息?
其中前三个最重要。
你的汇报如果能回答这个问题,会比单纯介绍目录强很多。
假设来了 NPU Gen N+1,你可以从代码总结它需要改哪些层:
textNew NPU │ ┌───────────┴───────────┐ ▼ ▼ Arch definition Feature set │ │ └───────────┬───────────┘ ▼ Subtarget │ ┌───────────────┼──────────────┐ ▼ ▼ ▼ Intrinsic Lowering New Instr support rule / *.td │ │ │ └───────────────┼──────────────┘ ▼ Scheduling Model │ ▼ MC / Binary
然后给领导一个结论,例如:
CCEC 的多代支持不是复制一套 backend,而是尽可能复用公共编译流程,将代际差异收敛到 Architecture/Feature → Subtarget → Lowering/Instruction/Scheduling 几个层次。
当然,这句话最后必须根据你看到的实际代码确认。如果实际代码大量 if (arch == XXX),那反而是个非常值得讲的架构观察。
这是你一天半里性价比最高的事情。
找一个非常简单的 intrinsic/kernel,例如:
cppvector_add
或者一个简单的:
cppDataCopy vector intrinsic cube intrinsic
然后追踪:
text源码 ↓ Builtin / Intrinsic ↓ LLVM IR ↓ CCE-specific Pass ↓ ISel / Lowering ↓ MachineInstr ↓ 最终 NPU Instruction
不要追复杂算子。
有了这一条以后,你前面所有内容都能落地:
一条 case 顶读十几个零散 Pass。
不要精读。
目标产物只有一张:
CCEC Code Map
先找到:
textmain/driver clang extension LLVM pass registration TargetMachine Subtarget InstrInfo *.td MC link tests
然后把实际目录填到:
textCCEC ├── Frontend ├── IR/MiddleEnd ├── Backend │ ├── Arch │ ├── Lowering │ ├── Instruction │ ├── Register │ └── Schedule ├── MC/Link └── Tests
此时禁止深入某个 Pass 超过 15 分钟。
选一个简单 kernel。
最终必须得到:
textSource ↓ XXX.cpp ↓ XXX intrinsic ↓ XXX pass ↓ XXX lowering ↓ XXX instruction
这个才是你汇报的主心骨。
全局搜:
textarch npu_arch soc subtarget feature hasFeature isArch CPU generation dav
尤其从:
text--npu-arch
向下追。
然后做一个表:
| 差异 | Gen A | Gen B | 代码控制位置 |
|---|---|---|---|
| intrinsic | ✓ | ✓ | Subtarget/Lowering |
| instruction X | × | ✓ | InstrInfo/TableGen |
| datatype X | × | ✓ | Feature |
| scheduling | model A | model B | ScheduleModel |
哪怕最后只有 3 行真实例子,都非常有价值。
我建议最终 6~7 页 PPT 足够:
P1:CCEC 定位
textCCE/Ascend C → CCEC → NPU Binary
一句话定位。
P2:整体代码架构
textFrontend → LLVM IR → Optimization → Backend → MC/Link
下面标对应代码目录。
P3:一次编译到底发生了什么
放你真实追出来的 case。
P4:CCEC 的核心能力
textProgramming Model Optimization CodeGen Toolchain
不要列 30 项 feature。
P5:多代际架构
核心图:
textArch ↓ Feature/Subtarget ↓ Lowering / Instr / Schedule
P6:两个代际差异的真实代码案例
这是最重要的“我真的读了代码”的证据。
P7:总结
最好只讲三个判断:
- 架构上:CCEC 基于 LLVM XXX 层进行了主要 NPU 定制。
- 能力上:核心价值集中在 XXX lowering / instruction / memory / scheduling。
- 演进上:通过 XXX 机制隔离公共逻辑与 NPU 代际差异。
我会直接放弃:
除非它们跟多代际直接相关。
一天半最危险的情况就是上午打开一个 3000 行 XXXLowering.cpp,下午还在里面。
最后给你一个判断标准:你读完代码以后,只需要能够在白板上不看资料画出这张图,就已经基本达到目标:
textCCEC │ ┌───────────────┼────────────────┐ │ │ │ Frontend Middle-end Backend │ │ │ CCE/Ascend C NPU Pass ┌─────┴──────┐ Builtin LLVM Pass │ │ Common Subtarget │ ┌──────┼──────┐ │ │ │ Gen1 Gen2 Gen3 │ │ │ └──────┼──────┘ │ Lowering / ISel / Schedule │ Binary
如果只能额外深挖一个方向,我会选“多代际到底在哪几个代码层次分叉”。 这比多认识 20 个优化 Pass 更适合向领导汇报,因为它能直接说明 CCEC 的架构设计、可维护性和新芯片 bring-up 成本。