在cpp中,将代码块提取到meth导致sigsegv

问题描述 投票:0回答:1

以下是错误代码,它会在

ort_session.Run

中引发错误
#include "gtest/gtest.h"
#include "onnx_helper.h"
#include "ndarray.h"
#include "opencv_helper.h"
#include "vector_helper.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h>

class OnnxHelper2Test : public testing::Test {
protected:
//    static void SetUpTestCase() {
//    }
};

std::pair<std::vector<float>, Shape> handle_input_img(const std::string &input_img_path) {
    // Load the image using OpenCV
    cv::Mat input_mat = cv::imread(input_img_path);

    // Convert to float
    cv::cvtColor(input_mat, input_mat, cv::COLOR_BGR2RGB);
    input_mat.convertTo(input_mat, CV_32F);
    // Normalize

    input_mat /= 255.0;
    // Convert the preprocessed image to a vector of floats
    Ndarray<float> input_img = mat_to_ndarray(input_mat);

//    std::string r = xarr_to_str(xa);
    input_img.transpose({2, 0, 1});
//    const std::string &xa_str1 = xarr_to_str(xa);
//    std::cout << xa_str1 << std::endl;
    input_img.expand_dims(0);
//    const std::string &xa_str2 = xarr_to_str(xa);
//    std::cout << xa_str2 << std::endl;

    return {input_img.data, input_img.shape};
}

void handle_out_img(Ort::Value &output_tensor, const std::string &out_img_path) {
    // Post-process the output
    auto out_img = tensor_to_ndarray(output_tensor).get_sub(0);
    auto out_shape = out_img.shape;
//    float *data_ptr = const_cast<float *>(tensor_data);
//    cv::Mat out_img(out_shape[2], out_shape[3], CV_32FC3, data_ptr);

    // Transpose the image
    out_img.transpose({1, 2, 0});

    // Scale the image to the range [0, 255]
    out_img *= 255;
    out_img.clip(0, 255);
    std::vector<uint8_t> out_img_int_data(out_img.data.begin(), out_img.data.end());

    // Save the output image using OpenCV
    auto out_mat = cv::Mat(out_img.shape[0], out_img.shape[1], CV_8UC3,
                           out_img_int_data.data()); // CV_8UC3 means 8u uint8_t + channel 3

    cv::cvtColor(out_mat, out_mat, cv::COLOR_RGB2BGR);
    cv::imwrite(out_img_path, out_mat);
}

// Method to set up the ONNX Runtime session
Ort::Session newSess(const std::string &onnx_model_path) {
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "onnxruntime");
    Ort::SessionOptions se_opts;
    OrtCUDAProviderOptions cudaProviderOpts;
    cudaProviderOpts.gpu_mem_limit = 2 * 1024 * 1024 * 1024;
    se_opts.AppendExecutionProvider_CUDA(cudaProviderOpts);
    se_opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
    se_opts.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL);
    Ort::Session ort_session(env, onnx_model_path.c_str(), se_opts);
    return ort_session;
}

int main(int argc, char **argv) {
    // Load the ONNX model
    auto d = "/home/roroco/Dropbox/cpp/cpp_lib/test/fix/onnx";
    std::string onnx_model_path = std::format("{}/RealESRGAN_x4plus_anime_6B.onnx", d);

//    // Set up the ONNX Runtime session
//    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "onnxruntime");
//    Ort::SessionOptions se_opts;
//    OrtCUDAProviderOptions cudaProviderOpts;
//    cudaProviderOpts.gpu_mem_limit = 2 * 1024 * 1024 * 1024;
//    se_opts.AppendExecutionProvider_CUDA(cudaProviderOpts);
//    se_opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
//    se_opts.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL);
//    Ort::Session ort_session(env, onnx_model_path.c_str(), se_opts);
    auto ort_session = newSess(onnx_model_path);

    Ort::AllocatorWithDefaultOptions allocator;
    std::string input_name = ort_session.GetInputNameAllocated(0, allocator).get();
    std::string out_name = ort_session.GetOutputNameAllocated(0, allocator).get();

    // Perform inference
    std::vector<const char *> input_names = {input_name.c_str()};
    std::vector<const char *> out_names = {out_name.c_str()};

    Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator,
                                                            OrtMemType::OrtMemTypeDefault);

    // Load and preprocess input image
    std::string input_img_path = std::format("{}/small.jpg", d);

    auto [input_tensor_vector, input_shape] = handle_input_img(input_img_path);
    // Create the input tensor
    Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
            memoryInfo,
            input_tensor_vector.data(),
            input_tensor_vector.size(),
            input_shape.data(),
            input_shape.size());

    // Create a vector of input tensors
    std::vector<Ort::Value> input_tensors = {};
    input_tensors.push_back(std::move(input_tensor));
    std::vector<Ort::Value> out_tensors = ort_session.Run(Ort::RunOptions{nullptr}, input_names.data(),
                                                          input_tensors.data(), input_tensors.size(),
                                                          out_names.data(), out_names.size());

    // Handle the output image
    const std::string &out_path = std::format("{}/out.jpg", d);
    handle_out_img(out_tensors[0], out_path);
    std::cout << std::format("out to {}", out_path);
}

当我不使用 newSess 并将所有 newSess 代码放入 main 中时,它可以工作,以下是正确的代码

#include "gtest/gtest.h"
#include "onnx_helper.h"
#include "ndarray.h"
#include "opencv_helper.h"
#include "vector_helper.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h>

class OnnxHelper2Test : public testing::Test {
protected:
//    static void SetUpTestCase() {
//    }
};

std::pair<std::vector<float>, Shape> handle_input_img(const std::string &input_img_path) {
    // Load the image using OpenCV
    cv::Mat input_mat = cv::imread(input_img_path);

    // Convert to float
    cv::cvtColor(input_mat, input_mat, cv::COLOR_BGR2RGB);
    input_mat.convertTo(input_mat, CV_32F);
    // Normalize

    input_mat /= 255.0;
    // Convert the preprocessed image to a vector of floats
    Ndarray<float> input_img = mat_to_ndarray(input_mat);

//    std::string r = xarr_to_str(xa);
    input_img.transpose({2, 0, 1});
//    const std::string &xa_str1 = xarr_to_str(xa);
//    std::cout << xa_str1 << std::endl;
    input_img.expand_dims(0);
//    const std::string &xa_str2 = xarr_to_str(xa);
//    std::cout << xa_str2 << std::endl;

    return {input_img.data, input_img.shape};
}

void handle_out_img(Ort::Value &output_tensor, const std::string &out_img_path) {
    // Post-process the output
    auto out_img = tensor_to_ndarray(output_tensor).get_sub(0);
    auto out_shape = out_img.shape;
//    float *data_ptr = const_cast<float *>(tensor_data);
//    cv::Mat out_img(out_shape[2], out_shape[3], CV_32FC3, data_ptr);

    // Transpose the image
    out_img.transpose({1, 2, 0});

    // Scale the image to the range [0, 255]
    out_img *= 255;
    out_img.clip(0, 255);
    std::vector<uint8_t> out_img_int_data(out_img.data.begin(), out_img.data.end());

    // Save the output image using OpenCV
    auto out_mat = cv::Mat(out_img.shape[0], out_img.shape[1], CV_8UC3,
                           out_img_int_data.data()); // CV_8UC3 means 8u uint8_t + channel 3

    cv::cvtColor(out_mat, out_mat, cv::COLOR_RGB2BGR);
    cv::imwrite(out_img_path, out_mat);
}

// Method to set up the ONNX Runtime session
Ort::Session newSess(const std::string &onnx_model_path) {
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "onnxruntime");
    Ort::SessionOptions se_opts;
    OrtCUDAProviderOptions cudaProviderOpts;
    cudaProviderOpts.gpu_mem_limit = 2 * 1024 * 1024 * 1024;
    se_opts.AppendExecutionProvider_CUDA(cudaProviderOpts);
    se_opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
    se_opts.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL);
    Ort::Session ort_session(env, onnx_model_path.c_str(), se_opts);
    return ort_session;
}

int main(int argc, char **argv) {
    // Load the ONNX model
    auto d = "/home/roroco/Dropbox/cpp/cpp_lib/test/fix/onnx";
    std::string onnx_model_path = std::format("{}/RealESRGAN_x4plus_anime_6B.onnx", d);

    // Set up the ONNX Runtime session
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "onnxruntime");
    Ort::SessionOptions se_opts;
    OrtCUDAProviderOptions cudaProviderOpts;
    cudaProviderOpts.gpu_mem_limit = 2 * 1024 * 1024 * 1024;
    se_opts.AppendExecutionProvider_CUDA(cudaProviderOpts);
    se_opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
    se_opts.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL);
    Ort::Session ort_session(env, onnx_model_path.c_str(), se_opts);
//    auto ort_session = newSess(onnx_model_path);

    Ort::AllocatorWithDefaultOptions allocator;
    std::string input_name = ort_session.GetInputNameAllocated(0, allocator).get();
    std::string out_name = ort_session.GetOutputNameAllocated(0, allocator).get();

    // Perform inference
    std::vector<const char *> input_names = {input_name.c_str()};
    std::vector<const char *> out_names = {out_name.c_str()};

    Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator,
                                                            OrtMemType::OrtMemTypeDefault);

    // Load and preprocess input image
    std::string input_img_path = std::format("{}/small.jpg", d);

    auto [input_tensor_vector, input_shape] = handle_input_img(input_img_path);
    // Create the input tensor
    Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
            memoryInfo,
            input_tensor_vector.data(),
            input_tensor_vector.size(),
            input_shape.data(),
            input_shape.size());

    // Create a vector of input tensors
    std::vector<Ort::Value> input_tensors = {};
    input_tensors.push_back(std::move(input_tensor));
    std::vector<Ort::Value> out_tensors = ort_session.Run(Ort::RunOptions{nullptr}, input_names.data(),
                                                          input_tensors.data(), input_tensors.size(),
                                                          out_names.data(), out_names.size());

    // Handle the output image
    const std::string &out_path = std::format("{}/out.jpg", d);
    handle_out_img(out_tensors[0], out_path);
    std::cout << std::format("out to {}", out_path);
}

我认为两个代码是相同的,为什么第一个代码会引发错误

c++ artificial-intelligence onnx onnxruntime
1个回答
0
投票

它没有在文档中明确说明它确实如此,但我想

Ort::Session
保留对
env
的引用,一旦
newSess
返回,它就是一个悬空引用。您需要在
env
之外创建
newSess
:

Ort::Session newSess(Ort::Env& env, const std::string &onnx_model_path) {
    Ort::SessionOptions se_opts;
    OrtCUDAProviderOptions cudaProviderOpts;
    cudaProviderOpts.gpu_mem_limit = 2 * 1024 * 1024 * 1024;
    se_opts.AppendExecutionProvider_CUDA(cudaProviderOpts);
    se_opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
    se_opts.SetExecutionMode(ExecutionMode::ORT_SEQUENTIAL);
    Ort::Session ort_session(env, onnx_model_path.c_str(), se_opts);
    return ort_session;
}
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "onnxruntime");
auto ort_session = newSess(env, onnx_model_path);
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.