【发布时间】:2018-02-11 19:04:28
【问题描述】:
我要求 C++ 编译器生成一个机器编码函数,该函数对 const std::vector 的元素求和。
#include <vector>
int sum(const std::vector<int>& v)
{
int s = 0;
for(const auto e:v) s += e;
return s;
}
我用-O2 询问编译器x86_64 GCC 7.2。它只是说:
sum(std::vector<int, std::allocator<int> > const&):
mov rdx, QWORD PTR [rdi]
mov rcx, QWORD PTR [rdi+8]
xor eax, eax
cmp rdx, rcx
je .L4
.L3:
add eax, DWORD PTR [rdx]
add rdx, 4
cmp rdx, rcx
jne .L3
rep ret
.L4:
rep ret
我对带有-O1、-O2 和-O3 的编译器Clang 4.0.0 提出同样的要求。好吧!那是一篇完整的论文。它只是在-O1、-O2 和-O3 的文章中操纵了一些形容词。
类似的情况是 x86_64 ICC 17 和 -O2 和 x86_64 CL 19。
然后我返回编译器 x86_64 GCC 7.2 并使用 -O3。 x86_64 GCC 7.2 现在给出了一个冗长的输出。
【问题讨论】:
-
最好发布一个完整的示例,其中包含可以编译的代码或带有代码的 goldbolt 链接。现在,答案可能对您没有帮助。此外,虽然这个问题读起来很有趣,但使用尽可能具体的术语而不是“论文”等将有助于人们理解您的问题。
-
不看汇编很难解释它,但我猜你可能会看到“循环展开”,这是一种通过使用更多指令使代码运行得更快的技术。
-
这个函数很容易向量化,所以难怪编译器会向量化它。
-
@user62039 Godbolt 有一个“分享”按钮,您可以在其中创建一个链接,以便其他人可以看到代码、程序集以及您正在查看的所有其他内容。
-
组装长度是一个值得商榷的指标,但当涉及到循环时,它就完全没用了。是的,矢量化和展开版本更长,但在相同输入上需要的迭代次数要少得多。
标签: c++ gcc visual-c++ c++14 clang++