每个C指令对应多少个汇编指令?

13

我知道这个问题不可能绝对回答,但我只是想要一个大致的数字:

假设有一个相当大的C程序(成千上万行代码),平均会生成多少条汇编指令。换句话说,C到汇编指令的比率是多少?可以做出一些假设,比如“在目前的x86架构下”。

我尝试通过谷歌搜索得到这方面的信息,但没有找到任何有用的结果。

补充说明:注意到这个问题带来了多少混乱,我感觉需要解释一下:通过这个问题,我想知道实际意义上“3GHz”是什么意思。我完全意识到每赫兹吞吐量因架构、硬件、缓存、总线速度和月亮的位置而大相径庭。

我不需要一个精确和科学的答案,而是一个经验性的答案,可以放入可理解的范围内。

这不是一个简单的答案(正如我开始注意到的那样),这是我最好的努力。我知道C程序中生成的汇编代码行数取决于你正在做什么。 i ++ sqrt(23.1)不在同一个邻域,我知道这一点。此外,无论我从C中得到什么汇编代码,该汇编代码都会在处理器内转换为各种微码集,这又取决于您正在运行的是AMD、英特尔还是其他东西,以及它们各自的代数。我也意识到了这一点。

到目前为止,我得到的大致答案就是我想要的:足够大的项目平均每1行ANSI-C代码对应2行x86 ASM代码。今天的处理器可能平均每个时钟周期生成一条ASM指令,一旦流水线被填充,并且给出足够的样本。


1
你会根据这个问题的回答做出什么决定? - EvilTeach
8个回答

23

无法给出确定的答案。像int a;这样的语句可能不需要任何汇编代码,而像a = call_is_inlined();这样的语句可能需要20多行汇编代码。

您可以通过编译C程序,然后启动objdump -Sd ./a.out来自己查看。它将显示混合了汇编和C代码,因此您可以看到为一个C代码行生成了多少行汇编代码。例如:

test.c

int get_int(int c);
int main(void) {
    int a = 1, b = 2;
    return getCode(a) + b;
}

$ gcc -c -g test.c

$ objdump -Sd ./test.o

00000000 <main>:
int get_int(int c);
int main(void) { /* here, the prologue creates the frame for main */
   0:   8d 4c 24 04             lea    0x4(%esp),%ecx
   4:   83 e4 f0                and    $0xfffffff0,%esp
   7:   ff 71 fc                pushl  -0x4(%ecx)
   a:   55                      push   %ebp
   b:   89 e5                   mov    %esp,%ebp
   d:   51                      push   %ecx
   e:   83 ec 14                sub    $0x14,%esp
    int a = 1, b = 2; /* setting up space for locals */
  11:   c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%ebp)
  18:   c7 45 f8 02 00 00 00    movl   $0x2,-0x8(%ebp)
    return getCode(a) + b;
  1f:   8b 45 f4                mov    -0xc(%ebp),%eax
  22:   89 04 24                mov    %eax,(%esp)
  25:   e8 fc ff ff ff          call   26 <main+0x26>
  2a:   03 45 f8                add    -0x8(%ebp),%eax
} /* the epilogue runs, returning to the previous frame */
  2d:   83 c4 14                add    $0x14,%esp
  30:   59                      pop    %ecx
  31:   5d                      pop    %ebp
  32:   8d 61 fc                lea    -0x4(%ecx),%esp
  35:   c3                      ret

感谢您提供的非常生动的示例。遗憾的是,我更关心一个大致平均值,因为我知道某些操作存在开销,更不用说复杂函数了。但是,尽管如此,我认为在足够的代码行数下,汇编: C比率最终会趋于稳定。 - Henrik Paul

12

我不确定你所说的"C-instruction"是什么意思,也许是语句或行?当然,这会因为多种因素而有很大的变化,但在查看了我自己的一些示例程序后,它们中的许多都接近于2-1标记(每个LOC两个汇编指令),我不知道这意味着什么或者它可能如何有用。

您可以根据特定程序和实现组合自己找出答案,方法是要求编译器仅生成汇编代码(例如gcc -S),或者对已经编译的可执行文件使用反汇编器(但您仍需要源代码进行比较)。

编辑

仅供参考,基于你澄清你想要实现的目标(理解现代处理器每秒钟能够执行多少行代码):

虽然现代处理器可能以每秒3亿个周期运行,但并不意味着它可以每秒执行3亿条指令。以下是一些需要考虑的因素:

  • 许多指令需要多个周期才能执行(除法或浮点运算可能需要几十个周期才能执行)。
  • 大多数程序花费绝大部分时间等待诸如内存访问、磁盘访问等。
  • 许多其他因素,包括操作系统开销(调度、系统调用等),也是限制因素。

但总的来说,处理器非常快,可以在短时间内完成惊人的事情。


正如所说,我只是在询问大致的数字,而你的经验性2:1比例完美地回答了我的问题。谢谢你的回答。 - Henrik Paul
我必须问一下,你到底想做什么? - Robert Gamble
既然你坚持,我更或多或少试图实际理解3GHz处理能力的含义。现在,无论是十亿条指令每秒还是其十分之一,都并不重要,因为这仍然是一个可观的指标。 - Henrik Paul
另一方面,代码每个周期运行超过1条指令并不罕见。现代x86是4宽或5宽超标量乱序执行。Skylake在大多数SPECint基准测试中平均超过1 IPC。 - Peter Cordes
《现代微处理器90分钟指南》是一份非常好的介绍现代CPU的资料。没错,3 GHz并不等于每秒3亿条指令。相差甚远。x86指令每秒可以达到15亿或18亿(一个4 uop循环,其中2个uop是宏融合ALU+分支),也可能非常慢,例如0.1亿。(不计算在I/O上休眠的时间,只有在缓存未命中或其他停顿,如分支预测错误时才会成为瓶颈。) - Peter Cordes

4
那取决于具体情况!如果有人试图给出一个粗略的转换,我是不会相信的。
i++;这样的语句可以转换为单个INC AX指令。
包含许多参数的函数调用语句可能会产生几十条指令,因为堆栈需要为调用进行设置。
此外,编译器优化将以与您编写的方式不同的方式组装代码,从而消除指令。
还有一些指令在机器字边界上运行得更好,因此会在您的代码中散布NOP指令。

3
我认为你无法从这里尝试的内容中得出任何有关实际应用程序性能的有用结论。除非“不精确”意味着“在几个数量级内”。
你过于概括了,并且你对缓存等的解释是次要的,而它可能是完全主导的。
如果您的应用程序足够大,已趋于某个平均每行指令数,则它也足够大,需要考虑I/O或至少显著的RAM访问问题。

2

根据您的环境,您可以使用Visual Studio选项:/FAs

更多信息在此处


1

我不确定这个问题是否有一个真正有用的答案。毫无疑问,您将不得不选择体系结构(正如您所建议的那样)。

我的建议是:取一个合理大小的C程序。在gcc中使用“-S”选项并自行检查。它会生成汇编源代码,您可以自己计算该程序的比率。


1
RISC还是CISC?在C语言中,什么是“指令”?
总之,除非你非常具体地了解你正在处理的代码类型,否则你真的不知道。
您可以尝试查阅有关汇编优化和硬件/软件干扰交叉对话的学术文献,这是过去30-40年发生的事情。那里是您将找到有关您感兴趣的内容的某种真实数据的地方。(虽然我警告您,您可能会看到C-> PDP数据而不是C-> IA-32数据)。

1

你在其中一条评论中写道你想知道3GHz是什么意思。

即使CPU的频率并不重要。现代PC-CPU会大量交错和调度指令,它们获取和预取,缓存内存和指令,而且通常该缓存会被无效并丢弃。通过运行真实世界的性能基准测试可以获得最佳的处理能力解释。


是的,以高IPC和低IPC为极端例子,3GHz Skylake比3GHz Pentium 4快得多。但对于给定的微架构,性能确实随着频率提高而提高。除非您的代码在带宽或缓存未命中延迟方面受到内存限制。但通常缓存会起作用,并且频率与性能之间存在显着的比例关系。例如,对于Skylake,一个4宽度超标量乱序CPU,它可以每个时钟周期将最多4个uop发射到乱序后端。大多数指令解码为单个uop。有关x86 CPU每个周期可以执行的操作的更多信息,请参见https://agner.org/optimize/。 - Peter Cordes
@PeterCordes: 谢谢你的评论 - Agner的指南是非常有价值的。当然,你在体系结构方面完全正确 - 但话说回来,目前市场上有那么多的体系结构。即使你将架构限制在我写这篇答案(2011年)以来的主流CPU中,它们也是众多的。 - Sebastian Mach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接