我的代码如下:
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添加到sum是减慢我的程序的速度(这可能看起来有点奇怪,简单的添加会很慢,但我称这个函数为数百次,每次执行数百万次计算)。我唯一的理论是,因为总和处于不同的范围,使用它的操作需要更长时间。所以我编写了代码:
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的时间最多。
答案 0 :(得分:4)
我的理论是否正确,发生这种情况的原因是分配给不在当前范围内的变量需要更长的时间?
没有
你的探查器对你撒谎,并指出错误的延迟来源。如果没有someQuickCalc
的任何知识,那么在没有并行化的情况下,这段代码无法进行有意义的优化。所有其他操作都非常简单。
答案 1 :(得分:2)
分析器可以做什么是有限的。如果你已编译
通过优化,编译器可能重新安排了公平
一点代码,所以探查器不一定能分辨出哪一行
number与任何一个特定指令相关联。和
编译器和硬件都可以提供很多
重叠;在许多情况下,硬件将继续
下一条指令,即使前一条指令尚未完成,
在管道(和编译器)中留下许多操作
将安排代码,以便硬件可以做到这一点
有效)。因此,例如,子表达式inArr[i]
涉及内存访问,这可能会慢得多
比什么都重要。但执行不等待它;该
执行不会等到实际需要结果。 (如果
编译器非常聪明,可能会注意到arr[i]
访问未初始化的内存,这是未定义的行为,所以
它可以跳过访问权限,并为您提供任何旧的随机值。)
在您的情况下,编译器可能只是完整 循环内的优化,因此执行只是停滞 用于在您写入时完成流水线操作 循环外的变量。而剖析器就这样归属 所有的时间写这篇文章。
(我已经大大简化了:更多细节,我必须知道 更多关于实际处理器,并查看生成的代码 有无优化。)