<分区>
我目前有两个函数 A 和 B。
在没有任何标志的情况下编译时,A 比 B 快。
但是当使用-O1
或-O3
编译时,B 比A 快得多。
我想将该功能移植到其他语言,所以看来 A 是更好的选择。
但如果我能理解 -O3
是如何加速函数 B 的,那就太好了。是否有任何好的方法至少可以稍微了解 -O3
所做的优化类型?
标签 c gcc optimization
<分区>
我目前有两个函数 A 和 B。
在没有任何标志的情况下编译时,A 比 B 快。
但是当使用-O1
或-O3
编译时,B 比A 快得多。
我想将该功能移植到其他语言,所以看来 A 是更好的选择。
但如果我能理解 -O3
是如何加速函数 B 的,那就太好了。是否有任何好的方法至少可以稍微了解 -O3
所做的优化类型?
最佳答案
-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
美国电话电报公司:
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
美国电话电报公司:
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 ,您可以从中学到更多。
关于c - 我如何理解-O3 的优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57536701/