gpt4 book ai didi

c++ - 在 OpenCV 中测试 parallel_for_ 性能

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:35:01 25 4
gpt4 key购买 nike

我在 OpenCV 中测试了 parallel_for_,方法是与仅进行简单数组求和和乘法的正常操作进行比较。

我有一个包含 100 个整数的数组,每个整数分成 10 个,并使用 parallel_for_ 运行。

然后我也有正常的0到99的求和和乘法运算。

然后我测量了耗时,正常操作比 parallel_for_ 操作快。

我的 CPU 是 Intel(R) Core(TM) i7-2600 四核 CPU。parallel_for_ 求和运算耗时 0.002 秒(耗时 2 个时钟周期),乘法耗时 0.003 秒(耗时 3 个时钟周期)。

但正常操作需要 0.0000 秒(少于一次点击周期)求和和乘法。我错过了什么?我的代码如下。

测试类

#include <opencv2\core\internal.hpp>
#include <opencv2\core\core.hpp>
#include <tbb\tbb.h>
using namespace tbb;
using namespace cv;

template <class type>
class Parallel_clipBufferValues:public cv::ParallelLoopBody
{
private:
type *buffertoClip;
type maxSegment;

char typeOperation;//m = mul, s = summation
static double total;
public:
Parallel_clipBufferValues(){ParallelLoopBody::ParallelLoopBody();};
Parallel_clipBufferValues(type *buffertoprocess, const type max, const char op): buffertoClip(buffertoprocess), maxSegment(max), typeOperation(op){
if(typeOperation == 's')
total = 0;
else if(typeOperation == 'm')
total = 1;
}
~Parallel_clipBufferValues(){ParallelLoopBody::~ParallelLoopBody();};

virtual void operator()(const cv::Range &r) const{
double tot = 0;
type *inputOutputBufferPTR = buffertoClip+(r.start*maxSegment);
for(int i = 0; i < 10; ++i)
{
if(typeOperation == 's')
total += *(inputOutputBufferPTR+i);
else if(typeOperation == 'm')
total *= *(inputOutputBufferPTR+i);
}

}

static double getTotal(){return total;}

void normalOperation(){
//int iteration = sizeof(buffertoClip)/sizeof(type);
if(typeOperation == 'm')
{
for(int i = 0; i < 100; ++i)
{
total *= buffertoClip[i];
}
}
else if(typeOperation == 's')
{
for(int i = 0; i < 100; ++i)
{
total += buffertoClip[i];
}
}
}

};

主要

    #include "stdafx.h"
#include "TestClass.h"
#include <ctime>

double Parallel_clipBufferValues<int>::total;
int _tmain(int argc, _TCHAR* argv[])
{
const int SIZE=100;
int myTab[SIZE];
double totalSum_by_parallel;
double totalSun_by_normaloperation;
double elapsed_secs_parallel;
double elapsed_secs_normal;
for(int i = 1; i <= SIZE; i++)
{
myTab[i-1] = i;
}
int maxSeg =10;
clock_t begin_parallel = clock();
cv::parallel_for_(cv::Range(0,maxSeg), Parallel_clipBufferValues<int>(myTab, maxSeg, 'm'));
totalSum_by_parallel = Parallel_clipBufferValues<int>::getTotal();
clock_t end_parallel = clock();
elapsed_secs_parallel = double(end_parallel - begin_parallel) / CLOCKS_PER_SEC;

clock_t begin_normal = clock();
Parallel_clipBufferValues<int> norm_op(myTab, maxSeg, 'm');
norm_op.normalOperation();
totalSun_by_normaloperation = norm_op.getTotal();
clock_t end_normal = clock();
elapsed_secs_normal = double(end_normal - begin_normal) / CLOCKS_PER_SEC;
return 0;
}

最佳答案

让我做一些考虑:

准确性

clock() 函数根本不准确。它的节拍大约是 1/CLOCKS_PER_SEC 但它的更新频率以及它是否统一取决于系统和实现。参见 this post有关详细信息。

测量时间的更好替代方法:

试验和测试环境

措施总是受 errors 影响.代码的性能测量受到其他程序、缓存、操作系统作业、调度和用户事件的影响(短列表,远不止于此)。拥有better measure你必须重复 很多 次(比方说 1000 次或更多),然后计算平均值。此外,您应该准备尽可能干净的测试环境。

有关这些帖子测试的更多详细信息:

开销和可扩展性

在您的情况下,并行执行(和您的测试代码结构)的开销比循环体本高度得多。在这种情况下,使算法并行是没有成效的。并行执行必须始终在特定场景中进行评估、测量和比较。这不是加快一切速度的 Elixir 。看看这篇关于 How to Quantify Scalability 的文章.

例如,如果您必须对 100 个数字求和/相乘,最好使用 SIMD指令(在展开的循环中甚至更好)。

衡量一下!

尝试让你的循环体为空(或者执行单个NOP 操作或volatile 写入,这样它就不会被优化掉)。您将粗略测量开销。现在将其与您的结果进行比较。

关于这个测试的注意事项

IMO 这种测试非常无用。您无法以通用方式比较串行或并行执行。这是您应该始终针对特定情况进行检查的东西(在现实世界中,很多事情都会发生,例如同步)。

想象一下:你让你的循环体真的很“重”,你会看到并行执行的速度大大提高。现在你让你的真实程序并行,你会发现性能更差。为什么?因为并行执行会因锁、缓存问题或对共享资源的串行访问而变慢。

测试本身没有意义,除非您在特定情况下测试特定代码(因为有太多因素会起作用,您无法忽略它们)。这是什么意思?好吧,您只能比较您测试的内容...如果您的程序执行 total *= buffertoClip[i]; 那么您的结果是可靠的。如果您的真实程序做了其他事情,那么您必须用那个其他东西重复测试。

关于c++ - 在 OpenCV 中测试 parallel_for_ 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20538147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com