首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我如何理解-O3的优化?

我如何理解-O3的优化?
EN

Stack Overflow用户
提问于 2019-08-17 13:25:46
回答 2查看 208关注 0票数 0

我现在有两个函数AB

在没有任何标志的情况下编译时,AB快。

但在用-O1-O3编译时,BA快得多。

我希望将函数移植到其他语言,因此A似乎是一个更好的选择。

但是,如果我能够理解-O3如何能够加快B函数的速度,那就太好了。有什么好的方法至少可以稍微了解一下-O3所做的优化吗?

EN

回答 2

Stack Overflow用户

发布于 2019-08-17 15:09:31

-O3的功能与-O2相同,并且:

  • 功能的内联部分。
  • 执行函数克隆,使过程间常量传播更强。
  • 在石墨外进行回路交换。这可以提高循环嵌套上的缓存性能,并允许进行进一步的循环优化,比如向量化。例如,循环:
代码语言:javascript
复制
for (int i = 0; i < N; i++)
  for (int j = 0; j < N; j++)
    for (int k = 0; k < N; k++)
      c[i][j] = c[i][j] + a[i][k]*b[k][j];

被转换成

代码语言:javascript
复制
for (int i = 0; i < N; i++)
  for (int k = 0; k < N; k++)
    for (int j = 0; j < N; j++)
      c[i][j] = c[i][j] + a[i][k]*b[k][j];
  • 在可行的循环上应用展开和阻塞变换。在循环嵌套中,通过某种因素展开外部循环,并将产生的多个内部循环融合。
  • 有足够的信息,他们没有滚动太多的皮环。它还开启了完全循环剥离(即完全删除循环,迭代次数较少)。
  • 执行预测的共通优化,即重用在以前循环迭代中执行的计算(特别是内存负载和存储)。
  • 分裂的路径,导致循环支撑。这可以改进死代码消除和常见子表达式消除。
  • 提高大循环体上的缓存性能,并允许进行进一步的循环优化,如并行化或向量化。
  • 将具有循环不变条件的分支移出循环,并在两个分支上重复循环(根据条件的结果修改)。
  • 如果循环以变量步长在数组上迭代,则创建另一个假设步长始终为1的循环版本。例如:
代码语言:javascript
复制
for (int i = 0; i < n; ++i)
  x[i * stride] = …;

变成:

代码语言:javascript
复制
if (stride == 1)
  for (int i = 0; i < n; ++i)
    x[i] = …;
else
  for (int i = 0; i < n; ++i)
    x[i * stride] = …;

例如,以下代码:

代码语言:javascript
复制
unsigned long apply(unsigned long (*f)(unsigned long, unsigned long), unsigned long a, unsigned long b, unsigned long c) {
    for (unsigned long i = 0; i < b; i++)
        c = f(c, a);
    return c;
}

unsigned long inc(unsigned long a, unsigned long b) { return a + 1; }
unsigned long add(unsigned long a, unsigned long b) { return apply(inc, 0, b, a); }

优化add函数以:

英特尔语法

代码语言:javascript
复制
add:
  lea rax, [rsi+rdi]
  ret

AT&T

代码语言:javascript
复制
add:
  leaq (%rsi,%rdi), %rax
  ret

如果没有-O3输出,则为:

英特尔语法

代码语言:javascript
复制
add:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov QWORD PTR [rbp-8], rdi
  mov QWORD PTR [rbp-16], rsi
  mov rdx, QWORD PTR [rbp-8]
  mov rax, QWORD PTR [rbp-16]
  mov rcx, rdx
  mov rdx, rax
  mov esi, 0
  mov edi, OFFSET FLAT:inc
  call apply
  leave
  ret

AT&T

代码语言:javascript
复制
add:
  pushq %rbp
  movq %rsp, %rbp
  subq $16, %rsp
  movq %rdi, -8(%rbp)
  movq %rsi, -16(%rbp)
  movq -8(%rbp), %rdx
  movq -16(%rbp), %rax
  movq %rdx, %rcx
  movq %rax, %rdx
  movl $0, %esi
  movl $inc, %edi
  call apply
  leave
  ret

您可以使用标志和-masm=intel比较函数A、和B的输出汇编程序。

这个答案是基于http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html的,你可以从中学到更多。

票数 3
EN

Stack Overflow用户

发布于 2019-08-17 14:03:27

问题是

有什么好的方法至少可以稍微了解一下-O3所做的优化吗?

显然,我的意图是在不考虑实际代码的一般意义下回答这个问题,我看到的最好的答案是推荐阅读编译器的文档,特别是关于优化的文档

虽然GCC执行的每一个优化都有相应的选项标志,但大多数都是这样。文档指定在每个级别根据这些标志执行哪些优化,并指定每个单个标志意味着什么。这些解释中使用的一些术语可能是不熟悉的,但您至少应该能够收集到“稍微理解一下”。请在优化文档的最顶端开始阅读。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57536701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档