图编译公共基础结构约束文档
【免费下载链接】geGE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力,并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge
图等数据结构作为公共基础结构,在设计时易用性、兼容性应该优先考虑。公共基础结构是整个系统的基石,其设计质量直接影响上层模块的可维护性和可扩展性。以下从架构设计层面总结核心原则。
核心设计理念
公共基础结构的设计应遵循以下核心思想:
- 稳定性优先:基础结构一旦确立,变更成本极高,设计时必须考虑长期演进
- 最小依赖:减少对其他模块的依赖,提高独立性和可移植性
- 向后兼容:接口演化必须保持向后兼容,避免破坏现有代码
- 关注点分离:基础结构只提供通用能力,不感知具体业务逻辑
- 可观测性:内置必要的调试和监控能力,降低问题定位成本
1. 模块的独立性与内聚性
设计思想:模块应具有清晰的边界和明确的职责,依赖关系应当显式化、最小化。模块的内部实现细节不应外泄,外部依赖应当可控。
架构原则:
- 模块之间的依赖应当是显式的、单向的,避免隐式依赖导致的耦合
- 模块的拆分应当基于职责的内聚性,而非实现的技术细节
- 模块应当是自包含的,其依赖关系应当通过明确的接口声明
在GE中的具体体现:
- SO文件的依赖应当是显式的,避免隐式符号依赖(通过
ldd -r验证) - 基础结构的SO拆分(
libgraph.so与libgraph_base.so)应考虑不同部署场景 - 历史遗留的隐式依赖(特指libgraph_base对libgraph的依赖)不应继续扩大,需逐步清理
2. 模块边界的稳定性与可演化性
设计思想:模块边界应当相对稳定,能够在内部实现演化的同时保持外部接口的兼容性。边界的调整需要谨慎评估影响范围。
架构原则:
- 模块内部的实现细节可以自由演化,但外部接口必须保持稳定
- 边界的调整(如模块归属的变更)需要考虑所有使用场景
- 向后兼容性是接口演化的首要约束
在GE中的具体体现:
- CC文件在不同SO间的归属调整需评估多种部署场景(桩包、非桩包、tiny场景)
- 资源受限场景下的模块大小约束需要考虑
- 边界变更的影响面分析应覆盖所有可能的组合场景
3. 接口演化的兼容性保障
设计思想:接口是模块间协作的契约,接口的演化必须保证不破坏现有代码。即使是非公开的内部接口,也需要考虑兼容性。
架构原则:
- 接口的设计应当考虑未来可能的扩展需求
- 接口的演化应当优先通过新增接口,而非修改现有接口
- 接口的变更(包括参数、返回值、语义)需要评估所有调用方
在GE中的具体体现:
- 外部接口(external)和内部接口都需要考虑ABI兼容性
- 老版本组件与新版本基础结构的组合场景需要特别关注
- 接口扩展时优先新增接口,避免修改现有接口的默认参数
4. 可观测性与性能的平衡
设计思想:可观测性(日志、监控、调试)是系统可维护性的基础,但必须在性能开销和可观测价值之间取得平衡。
架构原则:
- 基础结构应当提供适度的可观测能力,但避免过度日志
- 热路径上的可观测性操作必须精心设计,避免性能劣化
- 可观测性的粒度应当可配置,适应不同场景的需求
在GE中的具体体现:
- 基础接口的日志打印需要考虑调用频次约束(如1秒内不超过2次)
- ERROR日志的一定要谨慎使用(调用方无法忽略,必须处理)
- 高频调用场景需要特殊的日志策略(采样、分级等)
5. 接口设计的鲁棒性原则
设计思想:接口设计应当预见到各种可能的调用场景,包括正常场景、边界场景、误用场景,通过设计而非文档来保证正确使用。
架构原则:
- 接口应当明确其调用约束(如是否可重入、线程安全性)
- 接口应当通过类型系统、断言等机制防止误用
- 接口的性能特性应当在设计中体现,而非事后优化
在GE中的具体体现:
- 图操作的接口需要考虑可重入性和幂等性
- 嵌套调用、重复调用等场景需要提前设计防呆机制
- 热路径接口的性能优化需要在设计阶段考虑(避免重复计算、临时对象创建)
6. 关注点分离与层次化设计
设计思想:公共基础结构应当专注于提供通用、抽象的基础能力,不应当感知具体业务逻辑。业务逻辑应当在更高层次的模块中实现。
架构原则:
- 基础结构应当提供领域抽象,而非业务规则
- 基础结构的状态应当是通用的、可复用的,而非业务特定的
- 业务逻辑的变化不应影响基础结构的接口和实现
在GE中的具体体现:
- 图数据结构不应包含业务状态(如
is_valid_flag_、need_iteration_等) - 业务相关的标记和属性应当在上层模块中维护
- 基础结构提供的操作应当是通用的图操作(存储、查询、修改)
7. 并发模型的明确性原则
设计思想:并发模型是模块设计的重要约束,必须在设计阶段明确。不明确的并发模型会导致难以复现的并发问题。
架构原则:
- 模块必须明确其并发模型(单线程、多线程读、线程安全等)
- 并发模型的选择应当基于使用场景和性能需求的权衡
- 并发模型的变化是破坏性变更,需要在设计阶段确定
在GE中的具体体现:
- 图基础结构当前采用单线程模型,不支持并发修改
- 并发安全由业务层保证,而非基础结构提供
- 未来若需支持并发,需要在设计阶段明确接口语义和使用约束
8. 跨平台一致性的可移植性原则
设计思想:公共基础结构可能在不同平台、不同编译环境下使用,必须保证行为的一致性。实现细节的选择不应引入平台差异。
架构原则:
- 避免依赖实现定义或未定义行为
- 选择具有确定性语义的数据结构和算法
在GE中的具体体现:
- 避免使用迭代顺序不确定的容器(如
unordered_map) - 模型文件的兼容性需要考虑不同编译器和标准库实现的差异
9. 可调试性与可维护性内置原则
设计思想:可调试性不应当是事后添加的功能,而应当在设计阶段内置。基础结构的可观测性是其内在质量的一部分。
架构原则:
- 数据结构的完整状态应当能够被观测和导出
- 新增字段或功能时必须同步更新可观测性支持
- 可观测性能力本身也应当易于扩展和维护
在GE中的具体体现:
- 图的序列化是主要的维测手段,必须保证完备性
- 新增字段时需要同步更新序列化逻辑
- 序列化格式需要考虑版本兼容性和可读性
【免费下载链接】geGE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力,并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考