Z-Xiong / OSTrack-mnn

Mnn version demo of [ECCV2022] Joint Feature Learning and Relation Modeling for Tracking: A One-Stream Framework.
17 stars 2 forks source link

GPU推理结果不正确 #1

Open whyb opened 1 year ago

whyb commented 1 year ago

前言

首先感谢 Z-Xiong 在OSTrack方面研究的付出和开源分享精神。👍

我有跟到 @Z-Xiong 曾经有为了解决这个问题在MNN上发过一个issue:https://github.com/alibaba/MNN/issues/2377 结论是因为 self.input_tensors_x 是 nc4hw4 布局,tmp input 是 nchw 布局,所以要在转换时使用--keepInputFormat参数保存原本格式。

问题描述:

应用上您的代码之后使用CPU运行非常完美。👍 但是如果我仅仅切换到使用GPU运算(Vulkan、OpenCL),则会使推理结果完全不正确。 我有尝试将BackendConfig的precision改成Precision_High,仍然没有作用。 请教可能是什么原因导致的呢?我对MNN框架还不熟,请见谅~ 下面是我对OSTrack::OSTrack()做的稍许改动代码片段:

OSTrack::OSTrack(const char *model_path) {
    this->mnn_net = std::unique_ptr<Interpreter>(Interpreter::createFromFile(model_path));

    MNN::BackendConfig backendConfig;
    backendConfig.precision = MNN::BackendConfig::Precision_High;
    backendConfig.power = MNN::BackendConfig::Power_High;

    // Set seesion.
    //cpu
    this->net_config.type = MNN_FORWARD_CPU;    //推理结果正确
    this->net_config.numThread = 8;

    //vulkan gpu
    this->net_config.type = MNN_FORWARD_VULKAN;   //推理结果不正确
    this->net_config.numThread = 8;
    this->net_config.backupType = MNN_FORWARD_VULKAN;    //推理结果不正确

    //ocl gpu
    this->net_config.type = MNN_FORWARD_OPENCL;     //推理结果不正确
    this->net_config.numThread = 8;
    this->net_config.backupType = MNN_FORWARD_OPENCL;     //推理结果不正确

    this->net_config.backendConfig = &backendConfig;
    this->net_config.mode = ScheduleConfig::Path::Mode::Tensor; //https://github.com/alibaba/MNN/issues/2510
    this->session =  this->mnn_net->createSession(this->net_config);
......
Z-Xiong commented 1 year ago

首先感谢您对这个开源项目的关注,非常感谢您发现了这个bug。针对这个问题我请教了MNN官方。他们给出的排查方法是这样的:

  1. 检查下代码里面是不是直接使用 tensor 的 host 指针,对 gpu 来说需要前后拷贝,或者用 map
  2. 用 ModuleBasic / BackendTest 等工具测试
  3. 更新 mnn 版本

你可以试一下,如果还是不行,我也尝试下。

whyb commented 1 year ago

首先感谢您对这个开源项目的关注,非常感谢您发现了这个bug。针对这个问题我请教了MNN官方。他们给出的排查方法是这样的:

  1. 检查下代码里面是不是直接使用 tensor 的 host 指针,对 gpu 来说需要前后拷贝,或者用 map
  2. 用 ModuleBasic / BackendTest 等工具测试
  3. 更新 mnn 版本

你可以试一下,如果还是不行,我也尝试下。

关于CPU和GPU推理结果不一致的问题,您说的MNN官方给出了三条排查方法,我有尝试上面提到的三个方法:

1.尝试过程:

原话:1. 检查下代码里面是不是直接使用 tensor 的 host 指针,对 gpu 来说需要前后拷贝,或者用 map。

2.尝试过程:

原话:2. 用 ModuleBasic / BackendTest 等工具测试

3.尝试过程:

原话:3. 更新 mnn 版本

jxt1234 commented 1 year ago
  1. 换用 vulkan 后端测试一下
  2. 看上去有可能是 image 越界,用 opencl 时,numberThread 设成 65 试下
jxt1234 commented 1 year ago

ModuleBasic 所需的文件夹可以用 testMNNFromOnnx.py 验证 onnx 时生成的文件夹

whyb commented 1 year ago
  1. 换用 vulkan 后端测试一下

    1. 看上去有可能是 image 越界,用 opencl 时,numberThread 设成 65 试下
  1. backendTest换成Vulkan后端测试结果:
    
    :: forwardType =7(Vulkan)  tolerance=0.05  precision=0(Normal)
    C:\Users\admin>> .\backendTest.out.exe "D:\model\OSTrack\models\ostrack-384-ep100.mnn" 7
    Test forward type: 7
    Tolerance Rate: 0.050000
    Open Model D:\model\OSTrack\models\ostrack-384-ep100.mnn
    The device support i8sdot:0, support fp16:0, support i8mm: 0
    Input: 384,384,3,1
    precision=0 in main, 271
    modeNum=1 in main, 276
    stopOp.c_str()=s  in main, 281
    4032: -65472.000000 != -632698304.000000
    244 - 0 is error

:: forwardType =7(Vulkan) tolerance=0.05 precision=1(High) C:\Users\admin>> .\backendTest.out.exe "D:\model\OSTrack\models\ostrack-384-ep100.mnn" 7 0.05 1 Test forward type: 7 Tolerance Rate: 0.050000 Open Model D:\model\OSTrack\models\ostrack-384-ep100.mnn The device support i8sdot:0, support fp16:0, support i8mm: 0 Input: 384,384,3,1 precision=1 in main, 271 modeNum=1 in main, 276 stopOp.c_str()=s in main, 281 4: 0.335693 != 0.796851 302 - 0 is error

:: forwardType =7(Vulkan) tolerance=0.05 precision=3(Low_BF16) C:\Users\admin>> .\backendTest.out.exe "D:\model\OSTrack\models\ostrack-384-ep100.mnn" 7 0.05 3 Test forward type: 7 Tolerance Rate: 0.050000 Open Model D:\model\OSTrack\models\ostrack-384-ep100.mnn The device support i8sdot:0, support fp16:0, support i8mm: 0 Input: 384,384,3,1 precision=3 in main, 271 modeNum=1 in main, 276 stopOp.c_str()=s in main, 281 4032: -65472.000000 != -632698304.000000 244 - 0 is error


2. 我将本Repo(OSTrack-mnn)的初始化部分修改了如下代码:
```cpp
MNN::BackendConfig backendConfig;
backendConfig.precision = MNN::BackendConfig::Precision_High;
backendConfig.power = MNN::BackendConfig::Power_High;
this->net_config.type = MNN_FORWARD_OPENCL;
this->net_config.numThread = 65;  //用 opencl 时,numberThread 设成 65 试下

GPU和之前numThread =8时效果无异,仍然报一大堆cl error。推理结果也不是预期,如下图所示: 圖片

换成Vulkan推理也同样离预期很远。

whyb commented 1 year ago
  1. 换用 vulkan 后端测试一下
  2. 看上去有可能是 image 越界,用 opencl 时,numberThread 设成 65 试下

@jxt1234 抱歉,上午的时候没有debug进到 MNN::Interpreter::createSession() 内部,后来发现其实是一直没有设置进去,其实 ScheduleConfig.modeScheduleConfig.numThread 是个union,之前是因为被mode覆盖掉了,下午将本项目换成了用 ScheduleConfig.numThread = 65 下使用OpenCL就完全正常得到期望推理结果了。

createSession时的CL Error的失败是出现在 Session::resize() 的 iter->allocMemory() 这一句: 圖片

很神奇这个number thread竟然可以影响到OpenCL的初始化时候的显存分配动作。。。 另外Vulkan后端仍然不准确,从推理结果的偏离方向看起来(错的形式不一样)似乎与OpenCL的问题不属于同一类问题。 再次非常感激两位的协助 @jxt1234 @Z-Xiong

whyb commented 1 year ago

@jxt1234 查了下了解到这个mode=65的作用是“禁止调优” + “OpenCL_MEMORY_BUFFER” 代表的含义。

OpenCL_MEMORY_BUFFER

OpenCL_MEMORY_IMAGE

疑惑

圖片

我在MNN上搜了下issue,发现类似问题:MNN/issues/2393 ,不清楚这是否AMD显卡支持不好的原因是MNN引擎的现有已知问题?谢谢~