我目前有两个功能 A 和 B 。
编译时没有任何标志, A 比 B 快。
但是使用-O1
或-O3
进行编译时, B 比 A 快得多。
我想将该功能移植到其他语言,所以似乎 A 是更好的选择。
但是,如果我能理解-O3
如何设法加快功能 B ,那就太好了。是否有任何好的方法至少可以使您对-O3
所做的优化类型有一点点了解?
答案 0 :(得分:3)
-O3
与-O2
相同,并且:
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];
转换为
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];
for (int i = 0; i < n; ++i)
x[i * stride] = …;
成为:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = …;
else
for (int i = 0; i < n; ++i)
x[i * stride] = …;
例如,以下代码:
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:
lea rax, [rsi+rdi]
ret
AT&T :
add:
leaq (%rsi,%rdi), %rax
ret
没有-O3
输出的是:
英特尔语法
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 :
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
您可以使用-S
标志和-masm=intel
比较功能 A 和 B 的输出汇编器。
此答案基于GCC documentation,您可以从中学到更多。
答案 1 :(得分:0)
问题所在
是否有至少至少对-O3完成的优化类型有轻微了解的好方法?
,并且显然是要在不考虑实际代码的情况下以一般意义回答问题,我认为最好的答案是建议阅读documentation for your compiler,尤其是{{3} }。
尽管并非所有GCC执行的优化都具有相应的选项标志,但大多数这样做。 docs根据这些标志指定在每个级别执行哪些优化,并且它们还指定每个标志的含义。这些解释中使用的某些术语可能并不熟悉,但是您应该至少能够“稍有理解”。一定要从优化文档的顶部开始阅读。