保存一个值会花费我多少时间?假设我有一个计算值 x,我将使用 2 次、5 次或 20 次。在什么时候保存计算的值而不是每次使用它时重新计算它会变得更优化?例子:
int a=0,b=-5;
for(int i=0;i<k;++i)
a+=abs(b);
或者
int a=0,b=-5;
int x=abs(b);
for(int i=0;i<k;++i)
a+=x;
第二种情况在多少 k 值下会产生更好的结果?另外,这个 RAM 依赖多少?
保存一个值会花费我多少时间?假设我有一个计算值 x,我将使用 2 次、5 次或 20 次。在什么时候保存计算的值而不是每次使用它时重新计算它会变得更优化?例子:
int a=0,b=-5;
for(int i=0;i<k;++i)
a+=abs(b);
或者
int a=0,b=-5;
int x=abs(b);
for(int i=0;i<k;++i)
a+=x;
第二种情况在多少 k 值下会产生更好的结果?另外,这个 RAM 依赖多少?
由于 for 循环内的值abs(b)
不会改变,编译器很可能会将两个片段优化为相同的结果,即abs(b)
只评估一次的值。
除了在真实场景中测量之外,几乎不可能提供答案。当您在代码中缓存数据时,它可能存储在寄存器中(在您提供的代码中很可能是),或者它可能被刷新到 L1 缓存或 L2 缓存......取决于循环是什么正在做(它使用了多少数据?)。如果该值缓存在寄存器中,则成本为 0,将其推得越远,检索该值所需的成本就越高。
一般来说,编写易于阅读和维护的代码,然后测量应用程序的性能,如果不好,则进行概要分析。找到热点,找出它们为什么是热点,然后从那里开始工作。我怀疑缓存与计算abs(x)
上述内容是否会成为实际应用程序中的热点。所以不要出汗。
在许多情况下,它从 k=2 产生更好的性能。你给出的例子是 . 不是一个。即使启用了低级别的优化,大多数编译器也会尝试执行这种提升。该值在最坏的情况下存储在本地堆栈上,因此可能会保持相当的缓存温暖,从而消除您的内存问题。
但它可能会被登记在册。
原始必须执行附加分支,重复计算并返回值。Abs 是编译器可能能够识别为 constexpr 和提升的函数的一个示例。
在开发自己的类时,这是您应该尽可能将成员和引用标记为解释的原因之一。
根据经验,在循环外存储该值不会花费太多(如果有的话),因为无论如何编译器很可能会将 abs(x) 的结果存储到寄存器中。事实上,当编译器优化这段代码时(假设你开启了优化),它要做的第一件事就是将 abs(x) 拉出循环。
您可以通过使用“register”提示限定您的“x”声明来进一步帮助编译器生成好的代码。如果可能,这将要求编译器将 x 存储到寄存器值中。
如果您想查看编译器实际上对您的代码做了什么,要做的一件事是告诉它编译而不是汇编(在 gcc 中,选项是 -S)并查看生成的汇编代码。在许多情况下,编译器会生成比您手动优化的代码更好的代码。但是,也没有理由不自己进行这些简单的优化。
附录:
编译上述代码并在 GCC 中打开优化将导致代码等效于:
a = abs(b) * k;
试试看。
我会建议(这没有测试你的想法)
int x=abs(b)
循环外的示例会更快,因为你避免在每次迭代中分配堆栈帧以调用 abs()。
话虽如此,如果编译器足够聪明,它可能会弄清楚你在做什么并为两者生成相同(或相似)的指令。