首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我如何证明或反驳编译的效率?

我如何证明或反驳编译的效率?
EN

Stack Overflow用户
提问于 2013-09-11 08:38:18
回答 3查看 241关注 0票数 3

这是一个不寻常的问题,但我真的希望有一个明确的答案。

关于编译器如何高效地生成代码,特别是指令的数量,在我们的办公室里有一个长期的争论。我们为几乎没有循环的低功耗嵌入式系统编写代码。因此,发出的指令数量与功耗成正比。

我们的大部分代码看起来像这样(注意,没有动态内存分配,没有系统调用,很少的函数调用,很少的循环)。

代码语言:javascript
运行
复制
foo += 3 * (77 + bar);
if (baz > 18 - qux)
    bar -= 19 + 7 >> spam;

我可以用-O3编译上面的代码片段并读取程序集,但我不能自己编写它。

我想要证明或反驳的说法是,编译器生成的代码比手工编写的汇编代码“胖”2-4倍(因此消耗的功率是手写汇编代码的2-4倍)。

我对任何你有经验的编译器都感兴趣。

this answer我知道,GCC和clang可以发出与C代码交错的程序集,使用

代码语言:javascript
运行
复制
gcc -g -c -Wa,-alh foo.cc

这些答案提供了坚实的基础:

When is assembly faster?

Why do you program in assembly?

如何衡量编译器生成代码的效率?

EN

回答 3

Stack Overflow用户

发布于 2013-09-11 09:41:49

手工汇编即使不能击败编译器,也至少可以与编译器相匹敌,因为至少,你可以从编译器生成的汇编代码开始,并对其进行调整,使其变得更好。要真正做好这项工作,您需要了解CPU体系结构(流水线、功能单元、内存层次结构、乱序调度单元等)。以便您可以调度每条指令以获得最大效率。

另一件要考虑的事情是,指令的数量不一定与性能成正比,无论是速度还是功率(参见Hennessey和Patterson的Computer Architecture: A Quantitative Approach)。基本上,除了指令的数量(和时钟频率)之外,您还必须查看每条指令需要多少个时钟周期,才能知道它将花费多长时间。要知道将消耗多少能量,您还需要知道每条指令需要多少能量。

CPU如何实现每条指令会影响它执行所需的周期。例如,您的代码序列有一个>>运算符。编译器可能会将其转换为单个ASR指令,但是如果不知道体系结构,就无法知道它可能需要多少个时钟周期--一些体系结构可以在单个周期内进行任意移位,而另一些体系结构则需要为每个位移位使用一个周期。

内存访问也会增加周期数和功耗。当有太多的变量要存储在寄存器中时,其中一些变量将不得不存储在内存中。如果您正在访问片外内存,并且具有相当高的CPU时钟频率,则内存总线可能非常耗电。避免从存储器读取和向存储器写入(例如,通过计算两次相同的结果)的更长的指令序列可以更便宜。

正如其他一些人所建议的那样,基准测试是不可替代的。假设您使用的是具有恒定输入电压的基于微控制器的系统,您最好的选择是使用每组可选的代码来测量系统的电流消耗,并看看哪种方法做得最好(一种方法是使用电流探头和数字存储示波器)。

即使你能写出比编译器更好的汇编器,在开发时间和可维护性上也是有代价的。在The Mythical Man Month中,布鲁克斯估计,当许多程序员(如果不是大多数)用汇编语言编写代码时,工作量会增加3-5倍。除非你的代码真的很小,否则你最好只编写汇编中最关键的部分。即便如此,编写程序集的人应该能够通过比较运行代码和运行代码来证明他们的(更昂贵的)代码是值得的。

票数 3
EN

Stack Overflow用户

发布于 2013-09-11 09:06:56

如果问题是“我如何衡量编译器生成代码的效率”(你的实际问题),答案是“那要看情况”。这取决于你如何定义“效率”。大多数情况下,编译器都是为速度而设计的。当你改变优化级别(-O1, -O2, -O3)时,编译器会花更多的时间去寻找“能让它更快一点的聪明的事情”。这可能涉及循环展开、执行顺序、寄存器的使用,以及许多其他事情。

似乎你的“效率”标准并不是编译器设计的目标:你说你想要“最少的周期”,因为你认为==的功耗最低。然而,我认为“最快的执行”==“在处理器可以再次进入待机模式之前的最短时间”。除非你相信处理器在“唤醒”模式下的功耗随着指令的执行而发生显著变化,我认为可以肯定地说,最快的执行==最短的时间唤醒==最低的功耗。

在这种情况下,“胖代码”无关紧要--它只是为了提高速度。还要注意,并非所有指令都占用相同数量的时钟周期(尽管公平地说,这取决于处理器)。

票数 2
EN

Stack Overflow用户

发布于 2013-09-11 08:57:29

编辑,好的,这很有趣...

那些做出编译器优于人类的笼统说法的人,是那些没有真正检查过的人。编译器可以创建的任何东西,人类都可以创建。但是编译器不能总是创建人类可以创建的代码。就是这么简单。对于任何地方的项目,从几行到几十行或更大,由编译器手动修复优化变得越来越容易。编译器和目标有助于缩小这一差距,但总会有受过教育的人能够达到或超过编译器的输出。

我想要证明或反驳的说法是,编译器生成的代码比手工编写的汇编代码“胖”2-4倍(因此消耗的功率是手工编写的2-4倍)。

除非你对“胖”的定义是使用那么多的能量。二进制文件的大小和功耗并不相关。即使这样做了,也会有人做一个编译器,只让你的代码高效,他们不能也不会为这个星球上的每个系统调优编译器。不会发生的。

如果你说的是一个非常受控制的手机环境,应用程序可能会进行调整以节省电力,但编译器不是这方面的主人,它是用户,编译器做了一部分,其余的都是程序员手动调整的。

代码语言:javascript
运行
复制
I can compile the above snippet with -O3 and read the assembly, but I couldn't write it myself.

如果你带着这样的态度去做这件事,那么你就会自动地失败。是的,你可以遇到或击败编译器,句号。这是一个信心、意志力和时间/努力的问题。这句话意味着你还没有真正研究过这个问题,这就是为什么你在问你正在问的问题。这个问题完全是关于观点的,会引发火焰之战,诸如此类的问题将被关闭,并最终从这个网站上删除。相反,编写、编译和发布代码段,并询问“为什么编译器会产生这个输出,为什么不这样做?”这些类型的问题有更好的机会得到真正的答案,并留在这里供他人学习。

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

https://stackoverflow.com/questions/18730922

复制
相关文章

相似问题

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