Comments (3)
业务侧常见问题
支持opencl后端的手机众多,从gpu厂商到型号都有较大差异,在对接过程中也遇到极大的困难和挑战,可以将问题归类如下:
OpenCL后端初始化:手机GPU特殊机型case
- cl::Context与KernelContext/CLContext:与Lite框架里的定义存在不同,Lite框架里有KernelContext为每个Kernel持有,但对OpenCL来说,一个设备一个CL::Context;
- libopencl.so:某些机型不具有libopencl.so;
- symbol:某些机型在libopencl.so里的符号不全,即lite框架里用到的符号在该手机的opencl动态库里没有。分为两种,必须和非必须;
- cl设备:某些机型即使可以找到libopencl.so且符号完整,但在初始化设备类型时即OEPNCL_DEVICE_TYPE,会出现初始化失败的情况,即获取到的设备类型既不是CPU也不是GPU。在一款较老的arm mali gpu上遇到过;
- 安卓系统限制:在某些小众安卓OS系统如魅族,其厂商在系统层面对APP开发者在调用系统库如libopencl.so时进行了屏蔽,能使用的系统库存在一个或多个白名单位于手机上,能否使用该系统库需要查看白名单上是否具有该系统库;
- 对OpenCL后端的初始化容错:框架层面的问题,对OpenCL的初始化应该及时容错,即使初始化失败也不能Segfault挂掉(这种必须要解决),而是应该分为必要的abort和非必要的abort。
- 非必要abort:即必须容错,是初始化的过程,如CPU+GPU库,但即使是跑CPU模型,也有一定的对GPU的初始化流程,该过程不能因为该设备对GPU存在支持问题,导致挂掉影响了CPU的计算流程,这部分代码需要一定的解耦,同时要禁用abort;
- 必要abort:当CPU+GPU库跑GPU模型时,已成功完成必要的OpenCL初始化(无论CPU还是GPU模型,都必须经过的),在再后续的OpenCL初始化时,对不支持的情况务必abort。这时,就是已经确定是要运行GPU,但是确实有OpenCL的问题,那就必须abort。
- 业务层面的容错:业务层面对框架代码必须考虑容错,try-catch捕获异常。
驱动
- OpenCL驱动API内存泄露:arm mali,某荣耀机型
Kernel计算异常
- Mali/Adreno实现差异:通常是标量矢量类型等,该报错在build program过程就会暴露;
- Mac和移动端差异:image2d sampler采样器在
Normalized Coordinates
的不同; - 特殊机型(Adreno)矢量数组写入失败:寄存器限制;
- 缺少算子通用实现;
- 精度FP16误差大:不算bug,通过定位发现是逐层累计造成,类似int8导致的0.49999和0.50006问题,逐层累计,放大了误差。通过一套代码在FP32上运行,不存在精度问题。
用户使用
- 模型版本管理:模型中包含了模型转换工具opt的版本信息;
- cpu/gpu模型分不清:通过模型文件的明文信息可以确定cpu/gpu模型。
性能不符合预期
前文提到:
- 粗粒度:结构优化;
- 细粒度:逐个op Pofiler定位调优。
from opencl-101.
业务侧问题解决和思路
根据上面遇到的问题,除部分提到的解决思路外,大体解决方法有如下几类:
- 初始化问题
- 提供用户API——isOpenclBackendValid API
- 明确不同阶段挂的原因:
- isOpenclBackendValid API挂:找库、找符号、平台/设备/Context初始化等;
- Predictor创建挂:RuntimeProgram创建、KernelContext/CLContext(非cl::Context)赋值等;
- Predictor Run挂:LiteKernel/BuildProgram/OpenCL析构等等。
- 精度比对
- 依据ARM CPU的结算结果为正确基准,逐层比较精度Profiler;
- CL Kernel内:加打印printf对应某一线程的值,定位问题;
- FP16存在一定精度损失,可以使用
set_opencl_precision
跑FP32的;
- 性能问题(前文已提,简略)
- 结构(粗粒度)
- 逐OP(细粒度),性能Profiler
from opencl-101.
OpenCL Bug案例:解决和排查思路分析
案例1:不解决:driver内存泄露
- 表象:业务反馈跑gpu模型出现持续性内存增长;
- 排查:
- 用户API侧:加载模型、设置输入、获取输出、predictor执行分别for循环100w次,定位是predictor Run。涉及框架底层;
- 排除特殊op:尝试非业务模型、业务模型,均观察到有内存增长的情况。和业务模型的特殊op无关;
- 拆分原始模型为小模型:基于构建模型的脚本生成仅有conv、relu的一层小模型,转为部署模型,也存在内存增长情况。可能和io_copy、layout转换有关;
- 单元测试:使用conv/act的单元测试,该单元测试不包括io_copy和layout op转换,发现也存在内存增长;
- 进入conv实现:分为PrepareForRun、Run、ReInitWhenNeeded,分别放入100w次的for循环内进一步观察定位泄露点,定位到是Run部分,在对Run里的逐行代码分析,逐行放入100w次的for循环内,定位到是command_queue的enqueueNDRangeKernel在多次循环时有明显内存泄露情况;
- 观察是否是框架本身引入的问题:command_queue是实体非指针,观察其他框架tnn的调用方式,也是C++ OPENCL API,也存在泄露问题(需要多次运行),进一步观察其他框架(MNN/TFLite/TNN)也均有内存泄露问题;
- 确定该问题是gpu驱动bug,即该opencl的enqueueNDRangeKernel方法存在内存泄露。
- 解决方法:尝试升级手机系统,得到解决
案例2:解决:特殊机型OpenCL兼容性case-by-case
- 表象:找不到OpenCL库/库里符号不全/设备初始化失败/kernel类型不兼容/private memory写入失败/不支持FP16/…
- 解决:
- Host端问题:增加用户侧API,预判库/符号/设备/精度支持;
- OpenCL Kernel问题:改写为兼容性的实现(部分机型float与float4不支持互操作/某gpu不支持private的矢量数组定义如float4 a[4]导致部分写入失败);
- 精度问题:FP16精度低,增加精度设置API后,在一套kernel实现下,FP32精度下结果与ARM CPU一致。
案例3:解决:Conv随机中间结果
- 表象:安卓adb shell环境始终正确且无法复现,安卓APP环境中间层结果随机次数出错,出错值固定,
- 排查:
- 打印定位:检查conv输入、filter、param参数正确一致
- 单元测试定位:同规模无法复现;
- 怀疑opencl backend后端问题:中间过程排查了很多后端固有问题,如KernelContext的多Kernel持有问题等;
- 二分commit定位:仅半年的提交历史记录中,发现某次解决但后来只是减轻随机出错的次数,一直存在;
- 二分模型定位:基于原始模型的Paddle脚本二分模型,二分最小规模的三层模型;
- Kernel内打印定位:定位出随机出错的结果,逐步排查反推到conv op的激活函数值未初始化。
- 原因:conv param的激活函数成员未给初始化值,导致该值计算偶现随机化,arm cpu未出现该问题,但在gpu上出现。
案例4:规避:gpu模型cpu yolo_box计算结果不对
- 表象:在gpu模型中的cpu yolo_box算子计算结果不对,但cpu模型的yolo_box是正确的;
- 排查:yolo_box输入参数kernel计算前打印,中间过程计算结果打印;
- Cpu yolo_box单元测试同规模下无法复现;
- 解决:规避,实现yolo_box的gpu kernel。
from opencl-101.
Related Issues (20)
- 【论文解读】CLBlast: A Tuned OpenCL BLAS Library HOT 8
- cutlass: Efficient GEMM in CUDA
- The Midgard Shader Core HOT 1
- OpenCL与CUDA的区别
- CUDA kernel Optimization & libraries
- 【论文解读】CLTune: A Generic Auto-Tuner for OpenCL Kernels HOT 9
- 【竞品调研】MindSpore Lite的OpenCL AutoTune 策略 HOT 3
- The Utgard Shader Core
- 【渲染】Arm Mali: Tile-Based Rendering HOT 1
- FP32 operations/clock and Thread count
- Paddle-Lite OpenCL后端整体架构 HOT 2
- 【论文解读】A Note on Auto-tuning GEMM for GPUs HOT 2
- Matrix Multiply(A:Buffer, B:Image, C:Buffer) on Adreno GPUs HOT 14
- MNN Conv2d_int8 HOT 3
- TNN对mali的调度、cl&gl交互、subworkgroup的magic number HOT 4
- Adreno Architecture HOT 1
- GPU渲染流程 HOT 1
- PowerVR GPU Docs
- how to optimize opencl gemm HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from opencl-101.