Intel oneDNN 编程模型基础概念解析
oneDNN 项目地址: https://gitcode.com/gh_mirrors/mk/mkl-dnn
前言
Intel oneDNN(原MKL-DNN)是一个针对深度学习应用优化的高性能计算库。本文将深入解析其编程模型的核心概念,帮助开发者理解其架构设计思想和使用方法。
核心概念架构
oneDNN的编程模型围绕几个关键抽象构建,它们共同构成了一个高效的深度学习计算框架:
1. 原语(Primitives)
原语是oneDNN中最核心的抽象概念,代表一个特定的计算操作:
- 功能特性:可以表示前向卷积、LSTM反向计算或数据转换等操作
- 融合计算:通过属性(attributes)支持操作融合,如"卷积+ReLU"的复合操作
- 状态保持:不同于纯函数,原语可以保存状态
- 不可变状态:如张量形状等参数,可预计算缓存分块等优化参数
- 可变状态:称为暂存区(scratchpad),用于计算时的临时存储
设计优势:通过预计算优化参数,oneDNN可以生成针对特定操作优化的代码,虽然初始化耗时,但在多次执行相同操作时可显著提升性能。
2. 引擎(Engines)
引擎抽象了计算设备的概念:
- 代表特定的计算硬件:如CPU、特定GPU设备等
- 大多数原语绑定到特定引擎执行
- 重排序(reorder)原语是例外,可在不同引擎间传输数据
3. 流(Streams)
流封装了与特定引擎关联的执行上下文:
- 类似于OpenCL中的命令队列
- 管理计算任务的执行顺序和依赖关系
4. 内存对象(Memory Objects)
内存对象封装了以下关键信息:
- 特定引擎上分配的内存句柄
- 张量维度信息
- 数据类型
- 内存格式(张量索引到线性内存空间的映射方式)
抽象层次结构
oneDNN采用多层抽象设计,为开发者提供灵活性:
内存描述符(Memory Descriptors)
定义张量的逻辑属性:
- 逻辑维度
- 数据类型
- 内存布局格式
- 特殊格式
any
表示延迟指定实际格式
原语描述符(Primitive Descriptors)
完整定义计算操作:
- 基于内存描述符构建
- 包含操作属性
- 根据引擎分派具体实现
- 可查询实现细节而不需实例化原语
原语(Primitives)
最具体的实现层:
- 包含实际可执行代码
- 执行具体计算任务
创建流程详解
内存对象创建
创建步骤:
- 初始化内存描述符
- 直接构造
- 从现有张量提取子张量描述符
- 查询现有原语描述符获取
- 创建内存对象
- 可提供用户内存句柄
- 或由库自动分配
注意:不能从格式为any
的描述符直接创建内存对象
原语创建
标准流程:
- 创建原语描述符
- 可包含占位符格式(
any
)
- 可包含占位符格式(
- 基于描述符实例化原语
扩展功能
图扩展(Graph Extension)
高级抽象特性:
- 以计算图而非单个原语为单位工作
- 优势:
- 透明性:后端感知的融合逻辑对用户透明
- 可扩展性:无需修改代码即可利用新的融合模式
微内核扩展(Micro-kernel Extension)
低级抽象特性:
- 实现顺序块级操作
- 特点:
- 用户完全控制线程和分块逻辑
- 可组合块级计算实现自定义操作
最佳实践建议
- 原语重用:尽可能重用原语实例以分摊初始化成本
- 内存格式:合理使用
any
格式实现内存格式自动传播 - 实现选择:信任库默认选择的实现,通常是性能最优的
- 线程安全:注意暂存区的所有权影响线程安全性
总结
Intel oneDNN通过精心设计的抽象层次,在提供高性能计算能力的同时,保持了编程模型的灵活性和易用性。理解这些基础概念是有效使用该库的关键,能够帮助开发者在深度学习应用中实现最佳性能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考