ncnn extract遇到Segmentation fault

zmeyuzjn  于 3个月前  发布在  其他
关注(0)|答案(1)|浏览(51)

detail | 详细描述 | 詳細な説明

背景

模型为两个输入,一个输出。直接使用pnnx转换会出现不成功,信息如下

Exception raised from RAIIFile at ../caffe2/serialize/file_adapter.cc:21 (most recent call first):
frame #0: c10::Error::Error(c10::SourceLocation, std::string) + 0x57 (0x7fc31e6f84d7 in /home/ubuntu/.local/lib/python3.8/site-packages/torch/lib/libc10.so)

onnx2ncnn会出现

ScatterND not supported yet!
Unknown data type 0
Unknown data type 0
Tile not supported yet!
Tile not supported yet!

最终先转到了pt,再通过pnnx转换成功。

问题

  • c++集成ncnn-20240102-ubuntu-2004,通过net.output_names()发现有3个(实际只有1个),找到对应的name,然后extract,出现问题。
    -- 本地编译Debug版本得到以下堆栈信息
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f3b59ebe35e in ncnn::gridsample_3d_bilinear_apply_interpolation_p1 (src=..., dst=..., offset_value=..., opt=...)
    at /home/ubuntu/git/ncnn/ncnn-20240102/src/layer/x86/gridsample_bilinear_apply_interpolation.h:346
346                    float v000 = offset_ptr[0] >= 0 ? *(srcptr + offset_ptr[0]) : 0;
  • 怀疑与openmp有关,代码中注释掉了333行以及opt.num_threads设置为1,以上问题依然存在。
  • 怀疑仅cpu代码相关,使用vulkan推理,问题依然存在,信息如下
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fd014b1a76b in ncnn::GridSample_x86_fma::forward(std::vector<ncnn::Mat, std::allocator<ncnn::Mat> > const&, std::vector<ncnn::Mat, std::allocator<ncnn::Mat> >&, ncnn::Option const&) const () from /home/ubuntu/git/ncnn/ncnn-20240102/build/install/lib/libncnn.so.1
[Current thread is 1 (Thread 0x7fd00f591180 (LWP 1471998))]
(gdb) bt
#0  0x00007fd014b1a76b in ncnn::GridSample_x86_fma::forward(std::vector<ncnn::Mat, std::allocator<ncnn::Mat> > const&, std::vector<ncnn::Mat, std::allocator<ncnn::Mat> >&, ncnn::Option const&) const ()
    at /home/ubuntu/git/ncnn/ncnn-20240102/build/install/lib/libncnn.so.1
#1  0x00007fd0143d8636 in ncnn::NetPrivate::do_forward_layer(ncnn::Layer const*, std::vector<ncnn::Mat, std::allocator<ncnn::Mat> >&, ncnn::Option const&) const ()
    at /home/ubuntu/git/ncnn/ncnn-20240102/build/install/lib/libncnn.so.1
  • 对应前处理输入的代码如下
void cvConvert(const cv::Mat& image, ncnn::Mat* out) {
  *out = ncnn::Mat::from_pixels(image.data, ncnn::Mat::PIXEL_BGR, image.cols, image.rows);
  const float mean_vals[3] = {0.485f, 0.456f, 0.406f};
  const float std_vals[3] = {0.229f, 0.224f, 0.225f};
  out->substract_mean_normalize(0, std_vals);
  out->substract_mean_normalize(mean_vals, 0);
  out->reshape(1, out->c, out->h, out->w);
}

比较困惑,不知道问题出现在哪里。
求助大佬们解惑

7nbnzgx9

7nbnzgx91#

经过QQ群中nihui和calm大佬的指点,进一步定位了问题。先在这里做个记录
问题原因并不是offset_value越界导致,而是gridsample_3d_bilinear_compute_blob中对offset_value赋值的范围与gridsample_3d_bilinear_apply_interpolation_p1中访问的offset_value范围不一致,出现极大极小值后导致*(srcptr + offset_ptr[0])越界访问。

// in my case grid c: c: 5, d: 60, h: 80, w: 2, grid_size = 9600
// function gridsample_3d_bilinear_compute_blob
        const int grid_size = grid.w * grid.h * grid.d;   
        for (int y = 0; y < grid.c; y++) {
           for (; x < grid_size; x += 3) {
               ........
               offset_value_ptr += 11; // 这里会被赋值到grid_size * 11 / 3 * c = 176000
           }
         }

// function gridsample_3d_bilinear_apply_interpolation_p1
       for (int y = 0; y < grid.c; y++) {
          for (int x = 0; x < grid_size; x++) {
             const int* offset_ptr = (int*)offset_value_ptr;
             const float* value_ptr = offset_value_ptr + 8;
             float v000 = offset_ptr[0] >= 0 ? *(srcptr + offset_ptr[0]) : 0;
             ........
             offset_value_ptr += 11; // 这里会被访问到grid_size * 11 * c 
          }
       }

More
删除x86文件夹后使用非SIMD版本崩溃问题解决,但出现了结果错误的另一个问题。
SIMD/VULKAN的问题就辛苦大佬们解决了

相关问题