weixin_43449673 2023-09-11 09:51 采纳率: 50%
浏览 18
已结题

c++多线程模型速度问题

各位友友,现在我有一个c++程序,是跑模型的代码,现在的问题是我用一个初始化一个模型用一个线程跑速度在100ms,但是我初始化两个模型用两个模型并行计算的时候每个模型的速度就增加到了200ms,两个一起的化就差不多400-500ms了,这个问题怎么解决呢

img

img


#include "SamBox.h"
#include <opencv2/core/cuda.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
#include <regex>
#include <vector>
#include <thread>
#include <future>


// 找中心点
std::vector<cv::Point> find_center(cv::Mat img)
{
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    cv::findContours(img, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    std::vector<cv::Point> pointList;
    double area = 0;

    for (const auto &cnt : contours)
    {
        area = cv::contourArea(cnt);
        if (area > 9000)
        {
            cv::Moments M = cv::moments(cnt);
            int cX = static_cast<int>(M.m10 / M.m00);
            int cY = static_cast<int>(M.m01 / M.m00);
            pointList.push_back(cv::Point(cX, cY));
        }
    }
    return pointList;
}

void processImages(const std::vector<cv::String>& fileNames, SamBox* samBox) {
    cv::Mat blendedImage;
    cv::Mat mask; 
    for (const auto& filename : fileNames) {
        double iou;
        cv::Rect box_crop;  
        cv::Rect box_rect;    
        cv::Mat img = cv::imread(filename, -1);
        size_t pos0 = filename.find_last_of("/");
        std::string name = filename.substr(pos0+1);
        std::string inputStr = filename;
        int channels = img.channels();
        if (channels == 3)
        {
            cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
        }
        // 使用正则表达式匹配数字
        std::regex pattern(R"(\d+)");
        std::smatch matches;
        std::vector<std::string> numbers;

        // 从字符串中找到所有匹配的数字,并保存到vector中 
        while (std::regex_search(inputStr, matches, pattern)) {
            numbers.push_back(matches.str());
            inputStr = matches.suffix();
        }
        // 存储后面的四个匹配的数字
        int number1 = 0, number2 = 0, number3 = 0, number4 = 0;
        if (numbers.size() >= 4) {
            number1 = std::stoi(numbers[numbers.size() - 4]);
            number2 = std::stoi(numbers[numbers.size() - 3]);
            number3 = std::stoi(numbers[numbers.size() - 2]);
            number4 = std::stoi(numbers[numbers.size() - 1]);
        } else {
            std::cout << "Not enough numbers found.";
            
        }
        cv::Rect box = {number1,number2,number3,number4};
        auto start = std::chrono::high_resolution_clock::now(); 
        // 计算原始矩形框的中心点
        cv::Point center = cv::Point(box.x + box.width / 2, box.y + box.height / 2);
        // 计算新的矩形框的宽度和高度
        int newWidth = static_cast<int>(box.width * 2);
        int newHeight = static_cast<int>(box.height * 1.5);

        // 计算新的矩形框的左上角坐标
        int newX = center.x - newWidth / 2;
        int newY = center.y - newHeight / 2;
        cv::Mat image;
        box_crop = {newX, newY, newWidth, newHeight};
        bool flag;
        if( newX < 0 || newY < 0 || newWidth > img.size().width || newHeight > img.size().height ){
            image = img;
            flag = false;
            box_rect = {box.x,box.y,box.width,box.height};
        }
        else
        {
            image = img(box_crop);
            box_rect = {box.x-newX,box.y-newY,box.width,box.height};
            flag = true;
        }

        auto results = samBox->segmentImgs(image, box_rect);

        mask = results.first;
        iou = results.second;
        //将crop传入模型输出的mask还回原图尺寸大小
        if(flag){
            cv::Mat result_mask = cv::Mat::zeros(img.size(), img.type());
            mask.copyTo(result_mask(box_crop));
            mask = result_mask;
        }
        // 查找轮廓
        std::vector<std::vector<cv::Point>> contours;
        std::vector<cv::Vec4i> hierarchy;
        cv::findContours(mask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
        //在图像上绘制矩形框
        cv::rectangle(img,box.tl(),box.br(), cv::Scalar(0, 255, 0), 5);
        cv::drawContours(img, contours, -1, cv::Scalar(0, 0, 255), 5);
        cv::cvtColor(img, img, cv::COLOR_GRAY2BGR);
        auto end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> duration = end - start;
        std::cout << "all_time_2: " << duration.count() << " seconds" << std::endl;
        cv::imwrite("/home/jacc/samC++/res_img/"+name, img);
        std::cout << "............................................" << std::endl;
    }
    // }
}



int main(int argc, char **argv)
{   
    std::string folderPath = "/home/jacc/samC++/img_tray/60/";
    std::string fileExtension = ".jpg";
    std::vector<cv::String> fileNames;
    cv::glob(folderPath + "*" + fileExtension, fileNames);

    std::string folderPath1 = "/home/jacc/samC++/img_tray/70/";
    std::string fileExtension1 = ".jpg";
    std::vector<cv::String> fileNames1;
    cv::glob(folderPath1 + "*" + fileExtension1, fileNames1);

    // 初始化两个模型
    SamBox* samBoxA = new SamBox();
    SamBox* samBoxB = new SamBox();
    samBoxA->initializeSam();
    samBoxB->initializeSam();
        
    // 启动两个线程并行处理不同类别的图像
    std::thread threadA(processImages, fileNames, samBoxA);
    std::thread threadB(processImages, fileNames1, samBoxB);

    // 等待两个线程完成
    threadA.join();
    threadB.join();

    // 释放模型资源
    delete samBoxA;
    delete samBoxB;
}

  • 写回答

11条回答 默认 最新

  • 前网易架构师-高司机 优质创作者: 人工智能技术领域 2023-09-11 10:22
    关注

    你是几核CPU的?执行慢不一定是线程对CPU资源的抢占问题,你的是opencv加载和写文件,瓶颈可能在读写io上,建议你在读写资源前后打印下时间
    另外你的并行运算使用的是那种库mpi?并行执行的效率比多线程的效率高,你的并行化相当于是2个进程在同时跑,有自己独立的地址空间,而多线程快也是需要一个合理的线程模型的,所以我想知道你是需要一个设计来提升执行多个processImages任务的效率,还是只是做测试看看多线程的效率?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(10条)

报告相同问题?

问题事件

  • 系统已结题 9月19日
  • 已采纳回答 9月11日
  • 赞助了问题酬金15元 9月11日
  • 修改了问题 9月11日
  • 展开全部