繁体   English   中英

C ++线程创建开销很大

[英]c++ thread creation big overhead

我有以下代码,这让我很困惑:

float OverlapRate(cv::Mat& model, cv::Mat& img) {
    if ((model.rows!=img.rows)||(model.cols!=img.cols)) {
        return 0;
    }

    cv::Mat bgr[3];
    cv::split(img, bgr);

    int counter = 0;
    float b_average = 0, g_average = 0, r_average = 0;
    for (int i = 0; i < model.rows; i++) {
        for (int j = 0; j < model.cols; j++) {
            if((model.at<uchar>(i,j)==255)){
                counter++;
                b_average += bgr[0].at<uchar>(i, j);
                g_average += bgr[1].at<uchar>(i, j);
                r_average += bgr[2].at<uchar>(i, j);
            }
        }
    }

    b_average = b_average / counter;
    g_average = g_average / counter;
    r_average = r_average / counter;

    counter = 0;
    float b_stde = 0, g_stde = 0, r_stde = 0;
    for (int i = 0; i < model.rows; i++) {
        for (int j = 0; j < model.cols; j++) {
            if((model.at<uchar>(i,j)==255)){
                counter++;
                b_stde += std::pow((bgr[0].at<uchar>(i, j) - b_average), 2); 
                g_stde += std::pow((bgr[1].at<uchar>(i, j) - g_average), 2); 
                r_stde += std::pow((bgr[2].at<uchar>(i, j) - r_average), 2);                 
            }
        }
    }

    b_stde = std::sqrt(b_stde / counter);
    g_stde = std::sqrt(g_stde / counter);
    r_stde = std::sqrt(r_stde / counter);

    return (b_stde + g_stde + r_stde) / 3;
}


void work(cv::Mat& model, cv::Mat& img, int index, std::map<int, float>& results){
    results[index] = OverlapRate(model, img);
}

int OCR(cv::Mat& a, std::map<int,cv::Mat>& b, const std::vector<int>& possible_values)
{
        int recog_value = -1;
        clock_t start = clock(); 

        std::thread threads[10];
        std::map<int, float> results;
        for(int i=0; i<10; i++)
        {
            threads[i] = std::thread(work, std::ref(b[i]), std::ref(a), i, std::ref(results));
        }

        for(int i=0; i<10; i++)
            threads[i].join();


        float min_score = 1000;
        int min_index = -1;
        for(auto& it:results)
        {
            if (it.second < min_score) {
                min_score = it.second;
                min_index = it.first;
            }
        }

        clock_t end = clock();
        clock_t t = end - start;
        printf ("It took me %d clicks (%f seconds) .\n",t,((float)t)/CLOCKS_PER_SEC);

        recog_value = min_index;
}

上面的代码所做的只是简单的光学字符识别。 我有一个光学字符作为输入,并将其与0-9个十个标准字符模型进行比较,以获得最相似的一个,然后输出识别值。

当我在不使用同时运行的十个线程的情况下执行上述代码时,时间为7ms。 但是,当我使用十个线程时,对于单个光学字符识别,它下降到1或2秒。

是什么原因?? 调试信息告诉我们线程创建会消耗很多时间,这是以下代码:

threads[i] = std::thread(work, std::ref(b[i]), std::ref(a), i, std::ref(results));

为什么? 谢谢。

运行多个线程仅在2个上下文中有用:您有多个硬件核心(因此线程可以同时运行),或者每个线程都在等待IO(因此一个线程可以在另一个线程在等待IO的同时运行,例如磁盘负载或网络)传递)。

您的代码不受IO限制,所以我希望您有10个内核来运行代码。 如果您没有10个核心,那么每个线程将争夺稀缺资源,而最稀缺的资源就是L1缓存空间。 如果所有10个线程都在争夺1个或2个内核及其缓存空间,则缓存将“崩溃”,并使性能降低10-100倍。

尝试使用N = 1到10个线程运行10次不同的基准测试代码,并查看其性能。

(还有一个原因是拥有多个线程,这是内核支持超线程的时候。操作系统会“假装” 1个内核有2个虚拟处理器,但是这样做并不能获得2倍的性能。您可以获得1倍之间的性能提升。和2x。但是为了获得部分提升,您必须每个内核运行2个线程)

使用线程并非总是有效的。 如果在小问题上使用线程,则管理线程会花费更多的时间和资源,从而无法解决问题。 您必须为线程做好足够的工作,并对线程进行良好的管理。

如果您想知道在问题上可以使用多少个线程或必须有多少个问题,请从并行计算机的理论中找到同等有效的函数(psi1,psi2,psi3)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM