我有以下代码,这让我很困惑:
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));
为什么呢?感谢。
答案 0 :(得分:1)
运行多个线程仅在2个上下文中有用:您有多个硬件核心(因此线程可以同时运行)或者每个线程都在等待IO(因此一个线程可以在另一个线程等待IO时运行,如磁盘加载或网络传输)。
您的代码不受IO限制,因此我希望您有10个内核来运行您的代码。如果你没有10个内核,那么每个线程都将争夺稀缺资源,而最稀缺的资源就是L1缓存空间。如果所有10个线程都在争夺1或2个核心及其缓存空间,那么缓存将会是#34; thrashing&#34;并且给你10-100倍的性能。
尝试运行10次不同时间的代码基准测试,N = 1到10个线程,看看它是如何执行的。
(还有一个原因是拥有多个线程,这是核心支持超线程的时候。操作系统会假装&#34; 1核心有2个虚拟处理器,但是这样你不会得到2倍的性能。你得到1x和2x之间的东西。但是为了得到这个部分提升,你必须为每个核心运行2个线程)
答案 1 :(得分:0)
使用线程并不总是有效的。如果您在小问题上使用线程,那么管理线程会花费更多时间和资源,然后解决问题。你必须有足够的线程工作和良好的线程管理工作。
如果您想知道可以在问题上使用多少线程或者问题有多大,请从并行计算机理论中找到等效函数(psi1,psi2,psi3)。