Coder Social home page Coder Social logo

Comments (3)

ysh329 avatar ysh329 commented on June 12, 2024

业务侧常见问题

支持opencl后端的手机众多,从gpu厂商到型号都有较大差异,在对接过程中也遇到极大的困难和挑战,可以将问题归类如下:

OpenCL后端初始化:手机GPU特殊机型case

  1. cl::Context与KernelContext/CLContext:与Lite框架里的定义存在不同,Lite框架里有KernelContext为每个Kernel持有,但对OpenCL来说,一个设备一个CL::Context;
  2. libopencl.so:某些机型不具有libopencl.so;
  3. symbol:某些机型在libopencl.so里的符号不全,即lite框架里用到的符号在该手机的opencl动态库里没有。分为两种,必须和非必须;
  4. cl设备:某些机型即使可以找到libopencl.so且符号完整,但在初始化设备类型时即OEPNCL_DEVICE_TYPE,会出现初始化失败的情况,即获取到的设备类型既不是CPU也不是GPU。在一款较老的arm mali gpu上遇到过;
  5. 安卓系统限制:在某些小众安卓OS系统如魅族,其厂商在系统层面对APP开发者在调用系统库如libopencl.so时进行了屏蔽,能使用的系统库存在一个或多个白名单位于手机上,能否使用该系统库需要查看白名单上是否具有该系统库;
  6. 对OpenCL后端的初始化容错:框架层面的问题,对OpenCL的初始化应该及时容错,即使初始化失败也不能Segfault挂掉(这种必须要解决),而是应该分为必要的abort和非必要的abort。
    1. 非必要abort:即必须容错,是初始化的过程,如CPU+GPU库,但即使是跑CPU模型,也有一定的对GPU的初始化流程,该过程不能因为该设备对GPU存在支持问题,导致挂掉影响了CPU的计算流程,这部分代码需要一定的解耦,同时要禁用abort;
    2. 必要abort:当CPU+GPU库跑GPU模型时,已成功完成必要的OpenCL初始化(无论CPU还是GPU模型,都必须经过的),在再后续的OpenCL初始化时,对不支持的情况务必abort。这时,就是已经确定是要运行GPU,但是确实有OpenCL的问题,那就必须abort。
    3. 业务层面的容错:业务层面对框架代码必须考虑容错,try-catch捕获异常。

驱动

  1. OpenCL驱动API内存泄露:arm mali,某荣耀机型

Kernel计算异常

  1. Mali/Adreno实现差异:通常是标量矢量类型等,该报错在build program过程就会暴露;
  2. Mac和移动端差异:image2d sampler采样器在Normalized Coordinates的不同;
  3. 特殊机型(Adreno)矢量数组写入失败:寄存器限制;
  4. 缺少算子通用实现;
  5. 精度FP16误差大:不算bug,通过定位发现是逐层累计造成,类似int8导致的0.49999和0.50006问题,逐层累计,放大了误差。通过一套代码在FP32上运行,不存在精度问题。

用户使用

  1. 模型版本管理:模型中包含了模型转换工具opt的版本信息;
  2. cpu/gpu模型分不清:通过模型文件的明文信息可以确定cpu/gpu模型。

性能不符合预期

前文提到:

  1. 粗粒度:结构优化;
  2. 细粒度:逐个op Pofiler定位调优。

from opencl-101.

ysh329 avatar ysh329 commented on June 12, 2024

业务侧问题解决和思路

根据上面遇到的问题,除部分提到的解决思路外,大体解决方法有如下几类:

image

  1. 初始化问题
    1. 提供用户API——isOpenclBackendValid API
    2. 明确不同阶段挂的原因:
      1. isOpenclBackendValid API挂:找库、找符号、平台/设备/Context初始化等;
      2. Predictor创建挂:RuntimeProgram创建、KernelContext/CLContext(非cl::Context)赋值等;
      3. Predictor Run挂:LiteKernel/BuildProgram/OpenCL析构等等。
  2. 精度比对
    1. 依据ARM CPU的结算结果为正确基准,逐层比较精度Profiler;
    2. CL Kernel内:加打印printf对应某一线程的值,定位问题;
    3. FP16存在一定精度损失,可以使用set_opencl_precision跑FP32的;
  3. 性能问题(前文已提,简略)
    1. 结构(粗粒度)
    2. 逐OP(细粒度),性能Profiler

from opencl-101.

ysh329 avatar ysh329 commented on June 12, 2024

OpenCL Bug案例:解决和排查思路分析

案例1:不解决:driver内存泄露

  • 表象:业务反馈跑gpu模型出现持续性内存增长;
  • 排查:
    1. 用户API侧:加载模型、设置输入、获取输出、predictor执行分别for循环100w次,定位是predictor Run。涉及框架底层;
    2. 排除特殊op:尝试非业务模型、业务模型,均观察到有内存增长的情况。和业务模型的特殊op无关;
    3. 拆分原始模型为小模型:基于构建模型的脚本生成仅有conv、relu的一层小模型,转为部署模型,也存在内存增长情况。可能和io_copy、layout转换有关;
    4. 单元测试:使用conv/act的单元测试,该单元测试不包括io_copy和layout op转换,发现也存在内存增长;
    5. 进入conv实现:分为PrepareForRun、Run、ReInitWhenNeeded,分别放入100w次的for循环内进一步观察定位泄露点,定位到是Run部分,在对Run里的逐行代码分析,逐行放入100w次的for循环内,定位到是command_queue的enqueueNDRangeKernel在多次循环时有明显内存泄露情况;
    6. 观察是否是框架本身引入的问题:command_queue是实体非指针,观察其他框架tnn的调用方式,也是C++ OPENCL API,也存在泄露问题(需要多次运行),进一步观察其他框架(MNN/TFLite/TNN)也均有内存泄露问题;
    7. 确定该问题是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环境中间层结果随机次数出错,出错值固定,
  • 排查:
    1. 打印定位:检查conv输入、filter、param参数正确一致
    2. 单元测试定位:同规模无法复现;
    3. 怀疑opencl backend后端问题:中间过程排查了很多后端固有问题,如KernelContext的多Kernel持有问题等;
    4. 二分commit定位:仅半年的提交历史记录中,发现某次解决但后来只是减轻随机出错的次数,一直存在;
    5. 二分模型定位:基于原始模型的Paddle脚本二分模型,二分最小规模的三层模型;
    6. 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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.