机器学习 -- NCNN 特性总结 & ONNX

  • 整张图做计算,显存消耗太大,所以分块做,降低显存占用峰值。
  • 做视频超分时,传统做法是将视频解码出很多图片,针对每张图片做超分,最后将全部图片合成为视频。 通过多线程编解码,超分过程中使用多 GPU 和多 CPU 并行加速。
  • CPU 驱动长时间无法调度资源用于 UI 渲染,一次性提交大量 GPU 任务,影响 GPU 显示,UI 卡顿的问题。解决办法,将任务拆小。
  • GPU 模型加载问题。GPU 加载模型的时候有 shader 编译的过程,非常消耗资源和时间。 有些算子的参数是一样的,对参数做 hash,作为 key,只有第一次使用该算子的时候进行 shader 编译, 后面就可以直接复用编译好的 pipeline 对象,这样可以加速模型加载。
  • 内存池复用技术。后面的算子使用前面释放出来的算子所占用的内存。
  • 动态尺寸输入。输入多大图就计算多大图,无需 padding 到原图尺寸,节省时间。
  • 动态任务分配。在多任务网络中,根据前面的推理结果决定下一步推理流程。
  • 算子融合加速。两个运算合并成一个(比如 min 和 max),可以提高推理速度。
  • 手机大小核调度。
    • 大核心 CPU:速度快、耗电高。通过线程池绑定的方式,将在前台跑的、实时性要求很高的任务绑定在大核心 CPU 上。
    • 小核心 CPU:速度慢、耗电低。放一个在后台偷偷跑的任务,不会让前台卡顿。
  • OpenMP 里面的 busywait 过程。某个线程结束时并不会立即放弃 CPU,会使用自旋锁等待下一个任务分配,适合实时性要求较高,但是消耗 CPU 占用率。 禁用之可以降低 CPU 占用率。
  • 优化内存布局。
    • 推理框架的一般布局是(n,c,h,w)这样的布局下,遍历 channel 时指针是跳跃地访问地址的,有明显的访问延迟。 改为(h,w,c),将 channel 维放在最内层,每个像素对应的 c 个通道在内存中地址是连续的便于快速访问。
    • 使用 FP16 tensor 和 BF16 tensor 替换 FP32 tesor 可以节约内存。
  • 模型量化技术。浮点数做运算比整数更慢,功耗也更高。针对卷积层做量化处理,float32 转为 int8, 再只用整数的乘法和加法实现卷积层,最后输出 int32,再反量化,转为浮点数。

来源 在线管线缓存加速 ncnn gpu 模型加载

那么,离线管线缓存呢?

  • PC 上实验下来没有加速效果,因为驱动暗地里已经悄悄帮我缓存了。
  • 离线缓存,需要存出一个二进制文件,要设计新的接口,调用方也要加新的代码,具体怎么存储和加载没想清楚。
  • 最重要的问题,这个离线缓存如何保持兼容性?系统或驱动升级不兼容,换硬件不兼容,缓存文件损坏如何处理等等 …

  • 我当然是知道的,慢就慢在创建 pipeline 这里,vkCreateComputePipelines。 ncnn 每个 gpu 算子都是用 shader 拼出来的,模型里有各种 op,所有 op 的所有 shader 最终都要经过这里, 让驱动编译出 gpu 能跑的东西。shader 多了就慢了,而且因为某些驱动 bug,还不能多线程创建 pipeline。

onnxruntime-directml 1.16.3

pip install onnxruntime-directml

https://github.com/microsoft/DirectML https://onnxruntime.ai/docs/execution-providers/DirectML-ExecutionProvider.html https://github.com/microsoft/onnxruntime-inference-examples/tree/main/c_cxx/fns_candy_style_transfer https://github.com/microsoft/onnxruntime-inference-examples

https://github.com/fdwr/OnnxRuntimeDirectMLEPSample

https://www.nuget.org/packages/Microsoft.AI.DirectML/ 1.13.0 https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime.DirectML/ 1.16.3

NCNN 量化之 ncnn2table 和 ncnn2int8

https://www.cnblogs.com/armcvai/p/16948949.html https://zhenhuaw.me/blog/2019/neural-network-quantization-introduction-chn.html

int8 量化是利用 int8 乘法替换 float32 乘法实现性能加速的一种方法。 note 本文主要描述了 NCNN 中的量化工具操作过程,首先 NCNN 的量化工具包含两部分,ncnn2table 和 ncnn2int8;

在进行 ncnn2int8 量化过程之前需要进行 ncnn2table 操作,生成量化表;

下面首先介绍量化表的生成步骤:

一、ncnn2table 生成量化表

  1. 首先准备工作,参考 NCNN 深度学习框架之 Optimize 优化器
  2. 终端进入 ncnn/build/tools/quantize 目录
  3. ./ncnn2table –image imagepath –param parampath –bin binpath –output newModel.table
    • 注:在执行命令时,在后面还可以添加 mean, norm, size, thread 参数,这边工具里已设为默认,就没有修改;
    • 注:这里的 image 指的是图片集,并且是图片数量较多的图片集;
  4. 执行命令后,即可看见原文件目录下生成 newModel.table 的量化表

二、ncnn2int8 量化网络模型

  1. 执行可执行文件 ncnn2table,生成量化表
  2. 终端进入 ncnn/build/tools/quantizw 目录
  3. ./ncnn2int8 [inparam] [inbin] [outparam] [outbin] [calibration table]
  4. 执行命令后,即可在原文件目录下生成 param 和 bin 的输出文件(即进行 int8 量化后的 ncnn 模型)

构建

MT 64 dll

F:
cd F:\ncnnbuild
mkdir protobuf_build_MT64
cd protobuf_build_MT64
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=ON ../protobuf-3.11.2/cmake
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release -j 2
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --target install
F:
cd F:\ncnnbuild
mkdir ncnn_build_MT64
cd ncnn_build_MT64
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_DIR=F:/ncnnbuild/protobuf_build_MT64/install/cmake -DNCNN_SHARED_LIB=ON -DNCNN_VULKAN=ON ../ncnn
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release -j 2
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --target install

手工替换:<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> 为 MT。

这个脚本貌似没生效?!

# In case we are building static libraries, link also the runtime library statically
# so that MSVCR*.DLL is not required at runtime.
# https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
# This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
if (MSVC)
foreach(flag_var
    CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
    CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
  if (${flag_var} MATCHES "/MD")
    string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
  endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif (MSVC)

MT 32 dll

F:
cd F:\ncnnbuild
mkdir protobuf_build_MT32
cd protobuf_build_MT32
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" -A Win32 -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=ON ../protobuf-3.11.2/cmake
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release -j 2
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --target install
F:
cd F:\ncnnbuild
mkdir ncnn_build_MT32
cd ncnn_build_MT32
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 16 2019" -A Win32 -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_DIR=F:/ncnnbuild/protobuf_build_MT32/install/cmake -DNCNN_SHARED_LIB=ON -DNCNN_VULKAN=OFF ../ncnn
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release -j 2
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --target install

手工替换:<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> 为 MT。

ncnn-20240102-windows-vs2019-shared\x64mt_vulkan ncnn-20240102-windows-vs2019-shared\x86mt

pytorch 模型存储—转化为 ONNX

https://blog.csdn.net/Leo_whj/article/details/109736449

api-ms-win-core-heap-l2-1-0.dll missing

https://github.com/microsoft/onnxruntime/issues/15025 @skottmckay @fdwr "Windows builds are not compatible with Windows 8.x in this release. Please use v1.11 for now." great news, I looked dependency walker with onnxruntime.dll v1.11.1, it seems it doesn't depends on api-ms-win-core-heap-l2-1-0.dll.

https://github.com/microsoft/onnxruntime/pull/10796


参考资料快照
参考资料快照

本文短链接:
If you have any questions or feedback, please reach out .