c++ onednn(dnnl) c++如何使用oneapi深度神经网络库

千静君_8135

千静君_8135

2026-03-23

253人浏览

原创

必须先调用 dnnl_engine_create(&engine, dnnl_cpu, 0) 初始化 cpu 引擎,再调用 dnnl_stream_create(&stream, engine, dnnl_stream_default_flags) 创建流,所有 primitive 执行均需传入该 stream。

c++ onednn(dnnl) c++如何使用oneapi深度神经网络库

怎么初始化 dnnl_engine 和 dnnl_stream

不初始化就调用 dnnl_primitive 会直接 crash,不是报错而是段错误——因为 oneDNN(原 DNNL)所有计算都必须绑定到具体硬件上下文。CPU 和 GPU 引擎初始化方式不同,但绝大多数 C++ 项目起步只用 CPU。

常见错误是跳过 dnnl_engine_create 或传错 dnnl_engine_kind_t;比如误用 dnnl_gpu 却没装 Intel GPU 驱动或 oneDNN 的 GPU 后端,结果 dnnl_success 返回 false 但没检查返回值。

  • 先调 dnnl_engine_create(&engine, dnnl_cpu, 0),第二个参数固定为 dnnl_cpu,第三个是设备索引(CPU 总是 0)
  • 紧接着必须调 dnnl_stream_create(&stream, engine, dnnl_stream_default_flags),不能复用 engine 而漏掉 stream
  • 所有 primitive 执行都需传入这个 stream,哪怕只是创建 primitive 描述符(如 dnnl_inner_product_forward_desc_init)也依赖 engine

如何正确构造 memory descriptor(dnnl_memory_desc_t)

memory desc 是 oneDNN 最容易写错的一环:维度顺序、数据类型、内存格式 tag 三者必须严格匹配,否则 dnnl_primitive_desc_create 返回 dnnl_unimplemented 或运行时数值全零。

典型场景是卷积输入:NHWC 输入要转成 NCHW 才能被大多数 primitive 接受,但 oneDNN 不自动转换——你得手动指定 dnnl_format_tag_t,比如 dnnl_nchw,并确保 dims 数组按该 tag 解释。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • dims 是 int64_t 数组,顺序必须和 tag 一致:用 dnnl_nchw 就得是 {N, C, H, W},不是 {N, H, W, C}
  • 数据类型用 dnnl_f32 最稳;dnnl_bf16 需 CPU 支持 AVX512_BF16 指令集,否则 dnnl_primitive_desc_create 失败
  • 别直接传裸指针给 dnnl_memory_create;先用 dnnl_memory_desc_init_by_tag 初始化 desc,再用 dnnl_memory_create 绑定 buffer

为什么 dnnl_primitive_desc_create 总返回 dnnl_unimplemented

这不是 bug,是 oneDNN 的设计哲学:它只实现特定 layout + data type + algorithm 的组合。哪怕 dims 完全合法,只要 format tag 和算法不匹配,就拒绝创建 primitive 描述符。

最常踩的坑是默认用 dnnl_format_tag_any 以为能“自动适配”,结果后续 dnnl_primitive_create 时因内存 layout 不兼容而失败。oneDNN 不做隐式重排,_any 只是让库内部选一个它支持的 layout,但你后续必须用 dnnl_primitive_desc_query 拿到真实 layout 并按此准备 memory。

  • 调试时先打印 dnnl_status_t 返回值,别只看 nullptr 判定失败
  • 对卷积/全连接等,优先用明确 tag(如 dnnl_oihw 权重、dnnl_nchw 输入),避开 _any
  • 如果必须用 _any,立刻调 dnnl_primitive_desc_query_md(pd, dnnl_query_src_md, 0) 拿实际内存描述符,再据此分配 buffer

如何避免 dnnl_memory_map_data 崩溃或读出乱码

dnnl_memory_map_data 不是 memcpy 包装器,它是把 oneDNN 内部 memory object 映射到用户可读地址。崩溃往往因为 memory 对象生命周期结束早于 map,或者映射后没调 dnnl_memory_unmap_data 导致资源泄漏甚至下次 map 失败。

更隐蔽的问题是:GPU memory 无法用 dnnl_memory_map_data(会返回 dnnl_unimplemented),但 CPU memory 映射后若 buffer 被 primitive 在 stream 上异步修改,map 出来的指针内容可能未同步——你得先 dnnl_stream_wait(stream)。

  • 只对 CPU engine 创建的 memory 调用 dnnl_memory_map_data,GPU 请改用 dnnl_memory_get_data_handle + 自行 memcpy(且确保 host buffer 已 pin)
  • map 前确认 stream 已完成所有依赖操作:dnnl_stream_wait(stream) 必须在 map 之前
  • map 返回的指针不能长期持有;用完立即 dnnl_memory_unmap_data,否则后续 primitive 执行可能卡死
事情说清了就结束。注意:oneDNN 的 error code 很多是「不可恢复」的,比如 dnnl_invalid_arguments 或 dnnl_unimplemented,一旦出现,基本意味着你的 desc 构造逻辑有硬伤,而不是换个参数就能绕过去。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.31

2811

5

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

2025.10.31

534

9

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

2026.02.12

482

19

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1709

3

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.06.27

1211

7

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

969

5

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.25

2800

5

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

339

31

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

530

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习