2014-01-09 40 views
-3

我的代码如下:优化元件的总和在阵列

double a,b; //These variable are inputs to the function 
double *inArr; //This is also an iput to the function whose size is NumElements 
double *arr = new double[numElements]; //NumElements is ~ 10^6 
double sum = 0.0; 
for(unsigned int i=0;i<numElements;++i) 
{ 
    double k = a*inArr[i] + b; //This doesn't take any time 
    double el = arr[i]; //This doesn't take any time 
    el *= k; //This doesn't take any time 
    sum += el; //This takes a long time!!! 
} 

此代码越过每个时间计算的值k,对于每个元件它增加了k次该元素来总结数组的元素。我将代码分成了很多步骤,以便当我的分析器告诉我哪一行需要很长时间时,我将确切知道哪个计算是罪魁祸首。我的配置文件告诉我,将el加总是什么会减慢我的程序速度(这看起来有点奇怪,简单的加法会很慢,但我称这个函数为数百次,每次执行数百万次计算)。我唯一的理论是,因为总和在不同的范围,使用它的操作需要更长的时间。所以我编辑的代码是:

double a,b; //These variable are inputs to the function 
double *inArr; //This is also an iput to the function whose size is NumElements 
double *arr = new double[numElements]; //NumElements is ~ 10^6 
double sum = 0.0; 
for(unsigned int i=0;i<numElements;++i) 
{ 
    double k = a*inArr[i] + b; //This doesn't take any time 
    double el = arr[i]; //This doesn't take any time 
    el *= k; //This doesn't take any time 
    double temp = sum + el; //This doesn't take any time 
    sum = el; //This takes a long time!!! 
} 

现在sum操作花费很少的时间,即使它访问sum变量。这项任务现在需要很长时间。我的理论是否正确,发生这种情况的原因是分配给不在当前范围内的变量需要更长的时间?如果是这样,为什么这是真的?有什么办法可以快速完成这项任务吗?我知道我可以使用并行化来优化这个,我想知道我是否可以顺序地做得更好。我使用VS 2012以发行模式运行,我使用VS性能分析器作为分析器。

编辑:

一旦我删除了原来的访问inArr是什么是最耗时的优化。

+3

你为什么不使用'std :: accumulate(std :: begin(arr),std :: end(arr),0.0,[](auto sum,auto elem){return sum + elem * someQuickCaclc();});'?这应该会给你高度优化的代码。 – TemplateRex

+0

您是否尝试禁用优化(/ O1,/ O2)标志?这可以模仿一些分析。 –

+0

*您认为每条迭代所需的时间*“很长时间”*多长时间?飞秒?小时?天? – Roddy

回答

2

是有限制的什么分析器可以做。如果你已经编译 与优化,编译器可能已经重新安排一个公平 位的代码,因此分析器不一定能分辨出哪行 号码与任何一个特定的指令相关。而 编译器和硬件都将允许一个很好的协议的 重叠;在很多情况下,硬件只是去到 下一条指令,即使前一个还没有完成, 留在管道中的一些操作(和编译器 将安排代码,使硬件可以做这最有效地) )。因此,例如,子表达inArr[i] 涉及的存储器访问,这可能比什么都显著较慢 。但执行并不等待它;执行不会等到实际需要结果为止。 (如果 编译器是真聪明,它可以说此话arr[i] 访问未初始化的内存,这是不确定的行为,所以它 可以跳过访问,给你任何旧的随机值。)

在你的情况下,编译大概只能做全 优化内环路,所以执行只是拖延 的流水线操作,当你写 外循环的变量来完成。因此,剖析器始终将 归入此编写。

(我已经大大简化:对于更多的细节,我必须知道 更多实际的处理器,并查看生成的代码 有和没有优化。)

+0

谢谢,这很明显。所以你说这个简单的代码实际上不适合优化。这个速度和它的速度一样快,而且在这一点上profiler是非常没用的。 –

+0

也许吧。我不会说特定的机器不能做得更快,而且剖析器也没有用。分析器不会指出你需要调整哪一行,但它仍然可以告诉你一个变化是否改善了函数的整体性能。至于在功能上做了哪些改变,你或多或少都要猜测和试验。并且请注意,改善机器性能的改变可能会降低另一台机器上的代码速度。 (我没有看到你可以做什么来改善性能。) –

4

我的理论是正确的,这种情况发生的原因是分配给不在当前范围内的变量需要更长的时间?

你探查是骗你的,并查明延迟的错误来源。没有任何someQuickCalc的知识,此代码不能进行有意义的优化。所有其他的操作都非常简单。

+0

那么延迟的真正来源在哪里呢? –

+2

@BenjyKessler不可能从你发布的代码中说出来。 –

+0

好的,我会把someQuickCalc() –