PaddlePaddle/PaddleX

关于C#端部署的问题

zhoujianwen opened this issue · 8 comments

问题类型:模型部署
问题描述

在C#端无法正常使用GPU做推理

在C#端可以正常使用CPU加载模型与推理,但是使用GPU只能加载模型而不能正常推理,会提示如下错误信息。在C++环境下可以正常CPU和GPU的加载与推理,CPU与GPU的推理接口一样的。

image
image
image
W0206 01:15:36.804785 19100 device_context.cc:260] device: 0, cuDNN Version: 7.5.
引发的异常:“System.AccessViolationException”(位于 PaddleXCsharp.exe 中)
“System.AccessViolationException”类型的未经处理的异常在 PaddleXCsharp.exe 中发生
尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

“PaddleXCsharp.exe”(CLR v4.0.30319: PaddleXCsharp.exe): 已加载“D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Remote Debugger\x64\Runtime\Microsoft.VisualStudio.Debugger.Runtime.Desktop.dll”。已跳过加载符号。模块进行了优化,并且调试器选项“仅我的代码”已启用。
程序“[2484] PaddleXCsharp.exe: 程序跟踪”已退出,返回值为 0 (0x0)。
程序“[2484] PaddleXCsharp.exe”已退出,返回值为 -1 (0xffffffff)。

系统环境,Windows 10,i5 9400f ,DDR4 24G,RTX 2070 8G,Visual Studio 2019

cpu检测结果
image

请问您的c#端使用方式是不是类似 https://zhuanlan.zhihu.com/p/183875466 这篇文章这样用C#界面开发及dll调用呢?

@FlyingQianMM 是的,在C++跑CPU/GPU是没有问题的,但是在C#端只能跑CPU,而不能跑GPU,我把所有生成的dll文件都拷贝到debug目录下了,在debug的时候,gpu也能正确地加载model成功,但是断点到PaddlexDetPredict函数接收就不行了,CPU是没有问题的,目前也找不出问题所在。
另外我用C++加载自己生成的DLL接口,然后用GPU跑也是可以的,所以我的生成的DLL是没有问题。
paddlex 1.3.0

DEFINE_string(model_dir,
              ".\\xiaoduxiong_epoch_12\\inference_model_gpu",
              "Path of inference model");
DEFINE_bool(use_gpu, true, "Infering with GPU or CPU");
DEFINE_bool(use_trt, false, "Infering with TensorRT");
DEFINE_bool(use_mkl, true, "Infering with MKL");
DEFINE_int32(mkl_thread_num, omp_get_num_procs(), "Number of mkl threads");
DEFINE_int32(gpu_id, 0, "GPU card id");
DEFINE_string(key, "", "key of encryption");
DEFINE_string(image,
              ".\\xiaoduxiong_epoch_12\\xiaoduxiong.jpeg",
              "Path of test image file");
DEFINE_string(image_list, "", "Path of test image list file");
DEFINE_string(save_dir,
              ".\\xiaoduxiong_epoch_12\\output",
              "Path to save visualized image");
DEFINE_int32(batch_size, 1, "Batch size of infering");
DEFINE_double(threshold,
              0.5,
              "The minimum scores of target boxes which are shown");
DEFINE_int32(thread_num,
             omp_get_num_procs(),
             "Number of preprocessing threads");
 HMODULE hMod = LoadLibrary("detector.dll");  // dll路径

 int main(int argc, char** argv) {
    google::ParseCommandLineFlags(&argc, &argv, true);
    char* model_dir = (char*)FLAGS_model_dir.data();
    char* key = (char*)FLAGS_key.data();
    int* model_type = (int*)1;

    typedef void* (*CreatePaddlexModel)(int* model_type,
                                        char* model_dir,
                                        bool use_gpu,
                                        bool use_trt,
                                        bool use_mkl,
                                        int mkl_thread_num,
                                        int gpu_id,
                                        char* key,
                                        bool use_ir_optim);
    CreatePaddlexModel createmodel = (CreatePaddlexModel)GetProcAddress(hMod,
    TEXT("CreatePaddlexModel"));

    PaddleX::Model* model = (PaddleX::Model*)createmodel(model_type,
                                      model_dir,
                                      FLAGS_use_gpu,
                                      FLAGS_use_trt,
                                      FLAGS_use_mkl,
                                      FLAGS_mkl_thread_num,
                                      FLAGS_gpu_id,
                                      key,
                                      true);

      //PADDLEXLOG "CreadPaddleModel Success.\n");
      typedef bool (*PaddlexDetPredict)(void* model,
                                         unsigned char* img,
                                         int height,
                                         int width,
                                         int channels,
                                         int max_box,
                                      float* result,
                                         bool visualize);
      PaddlexDetPredict detpredict =
          (PaddlexDetPredict)GetProcAddress(hMod, TEXT("PaddlexDetPredict"));



      cv::Mat im = cv::imread(FLAGS_image, 1);
      unsigned char* img = im.data;
      // BYTE* img = im.data;
      int height = im.rows;
      int width = im.cols;
      int channels = im.channels();
      int max_box = 100;
      float* result = new float[max_box * 6 + 1];

      //delay_us(10);  // 延时
      bool isSuccess = 0;
      for (int i = 0; i < 100; i++) {
        isSuccess = detpredict(
            model, img, height, width, channels, max_box, result, 0);
        if (!isSuccess) {
          PADDLEXLOG "PaddlexDetPredict Error!\n");
        }
        //im.release();
      }


    system("pause");
    return 0;
}

证实在C++环境下引用该detector.dll加载模型与检测是没有问题的
image

@yzl19940819 帮忙跟进下这个问题~

我之前是使用多线程去处理 ,初次使用没有很好地管理资源同步的问题,由于gpu的处理速度(推理/11ms)实在太快了,而获取当前帧的数据又来不及处理完,下一帧的推理就开始了,导致原来的位置数据被覆盖了。
另外dll构建要注意版本和推理接口的管理,我测试的时候也是使用与官方一致的接口类型。
Paddle版本:fluid_inference_install_1.8.4_gpu
CUDA版本:
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:04_Central_Daylight_Time_2018
Cuda compilation tools, release 10.0, V10.0.13
CUDNN版本:7.5.0
OPENCV:opencv-3.4.6-vc14_vc15.exe

这个问题现在有解决方案了

这个问题现在有解决方案了

请问怎么解决的

我之前是使用多线程去处理 ,初次使用没有很好地管理资源同步的问题,由于gpu的处理速度(推理/11ms)实在太快了,而获取当前帧的数据又来不及处理完,下一帧的推理就开始了,导致原来的位置数据被覆盖了。
另外dll构建要注意版本和推理接口的管理,我测试的时候也是使用与官方一致的接口类型。
Paddle版本:fluid_inference_install_1.8.4_gpu
CUDA版本:
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:04_Central_Daylight_Time_2018
Cuda compilation tools, release 10.0, V10.0.13
CUDNN版本:7.5.0
OPENCV:opencv-3.4.6-vc14_vc15.exe

请问最后怎么处理的,我也遇到了,在C#多线程调用的时候报错,单线程或者CPU运行都没有问题