为什么我必须在g ++中启用优化才能进行简单的数组访问?

我在C ++(gcc / Linux)中使用了一个double s的std::vector编写了一个简单的高斯消元法。 现在我已经看到运行时依赖于编译器的优化级别(使用-O3速度提高了5倍)。 我写了一个小测试程序并收到了类似的结果。 问题不在于矢量的分配,也没有任何resize等。

陈述这是一个简单的事实:

 v[i] = x + y / z; 

(或类似的东西)没有优化就慢得多。 我认为问题是索引运算符。 如果没有编译器优化, std::vector比raw double *v慢,但是当我打开优化时,性能是相同的,令我惊讶的是,即使访问raw double *v也更快。

这种行为有解释吗? 我真的不是一个专业的开发人员,但我认为编译器应该能够将上述语句直接转移到硬件指令。 为什么需要启用优化,更重要的是,优化的缺点是什么? (如果没有,我想知道为什么优化不是标准。)

这是我的矢量测试代码:

 const long int count = 100000; const double pi = 3.1416; void C_array (long int size) { long int start = time(0); double *x = (double*) malloc (size * sizeof(double)); for (long int n = 0; n < count; n++) for (long int i = 0; i < size; i++) x[i] = i; //x[i] = pi * (in); printf ("C array : %li s\n", time(0) - start); free (x); } void CPP_vector (long int size) { long int start = time(0); std::vector x(size); for (long int n = 0; n < count; n++) for (long int i = 0; i < size; i++) x[i] = i; //x[i] = pi * (in); printf ("C++ vector: %li s\n", time(0) - start); } int main () { printf ("Size of vector: "); long int size; scanf ("%li", &size); C_array (size); CPP_vector (size); return 0; } 

我收到了一些奇怪的结果。 标准g ++编译为向量大小为20 000生成运行时8 s(C数组)或18 s( std::vector )。如果我使用//..后面更复杂的行,则运行时为8/15 s(是的,更快)。 如果我打开-O3那么,对于40,000矢量大小,运行时间为5/5秒。

为什么我们需要优化/调试版本?

优化可以完全重新排序指令序列,消除变量,内联函数调用,并使可执行代码远离您无法调试的源代码。 因此,不使用优化的原因之一是保持调试代码的可能性。 当您的代码(当您相信您的代码时)完全调试时,您可以打开优化以生成发布版本。

为什么调试代码慢?

  • 要记住的一件事是,STL的调试版本可能包含对迭代器的边界和有效性的附加检查。 这可能会使代码速度降低10倍。这已知是Visual C ++ STL的问题,但在您的情况下,您没有使用它。 我不知道gcc的STL的艺术状况。
  • 另一种可能性是您以非线性顺序访问内存,产生大量缓存未命中。 在调试模式下,编译器将重新生成代码并生成此低效代码。 但是当启用优化时,它可能会将您的访问重写为顺序访问,而不会产生任何缓存未命中。

该怎么办 ?

您可以尝试展示一个展示行为的简单可编辑示例。 然后我们可以编译并查看程序集来解释实际情况。 如果遇到缓存问题,您正在处理的数据大小重要。

链接

  • Visual C ++ STL在调试模式下运行缓慢: http : //marknelson.us/2011/11/28/vc-10-hash-table-performance-problems/
  • STL的调试版本对Visual C ++的作用是什么: http : //channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Advanced-STL/C9-Lectures-Stephan-T-Lavavej-Advanced -STL -3-的正
  • 缓存未命中及其影响: http ://channel9.msdn.com/Events/Build/2014/2-661,特别是29’27“
  • 再次缓存: https : //www.youtube.com/watch? v = fHNmRkzxHWs at 36’34“