与汇编相比,C效率低吗?

时间:2010-07-22 23:15:34

标签: c compiler-construction assembly

  

可能重复:
  When is assembler faster than C?

您好,

这纯粹是一个理论问题,因此,如果有一个“无限”的时间来制作一个简单的程序,以及C和汇编的高级知识,那么在汇编中做一些事情真的更好吗?将C编译成汇编(机器代码)时,“性能”会丢失吗?

根据性能,我的意思是,现代C编译器在某些任务中做得不好,这些任务可以直接在Assembly中加速编程吗?

谢谢。

11 个答案:

答案 0 :(得分:14)

在许多情况下,现代C可以比装配做得更好,因为跟踪哪些操作可以重叠以及哪些操作会阻挡其他操作是如此复杂,只能由计算机合理地跟踪。

答案 1 :(得分:13)

与任何事情相比,C效率不高。 C是一种语言,我们不会在效率方面描述语言。我们在效率方面比较程序。 C不写程序; 程序员编写程序。

与C比较时,程序集为您提供了极大的灵活性,这是以编程时间为代价的。如果你是一个大师C程序员和一个大师程序员程序员,那么你可能会在编写任何给定的程序时使用Assembly来挤出更多的果汁,但这个价格几乎肯定是令人望而却步的。

我们大多数人都不是这些语言中的大师。对于我们大多数人来说,将性能调优的责任赋予C编译器是一个双赢:你获得了许多汇编大师的智慧,编写C编译器的人,以及你手中的大量时间进一步纠正和增强您的C程序。你也可以获得便携性。

答案 2 :(得分:9)

这个问题似乎源于错误观念,即更高的性能会自动更好。从更高层次的角度来看,在一般情况下使组装变得更好是太多了。即使性能是您最关心的问题,编译器通常也能比您自己编写的更好地创建高效的汇编。他们对您的所有源代码有了更广泛的“理解”,而不是您可能掌握的内容。可以通过NOT使用结构良好的汇编来进行许多优化。

显然有例外。如果您需要直接访问硬件,包括CPU的特殊处理功能(例如SSE),那么组装就是最佳选择。但是,在这种情况下,您最好使用可以更直接地解决一般问题的库(例如数字包)。

但是你应该只担心这样的事情,如果你有一个具体的,特定的需要提高性能,你可以证明你的程序集实际上更快。具体的具体需求包括:注意和测量性能问题,性能是基本设计问题的嵌入式系统等等。

答案 3 :(得分:5)

对大多数任务使用C,并为特定任务编写内联汇编代码(例如,利用SSE,MME,......)

答案 4 :(得分:4)

除非您是汇编专家并且(/或)利用编译器未使用的高级操作码,否则C编译器可能会获胜。

尝试它的乐趣; - )

更现实的解决方案通常是让C编译器执行它,然后配置文件,如果需要,调整特定部分 - 许多编译器可以转储某种低级IL(甚至“汇编”)。

答案 5 :(得分:3)

忽略编写代码所需的时间,并假设您拥有在两种情况下最有效地完成任务所需的所有知识,根据定义,汇编代码始终能够满足或超越由C编译器生成的代码,因为C编译器必须创建汇编代码来执行相同的任务,并且它无法优化所有内容;和C编译器写的任何东西一样,你也可以编写(理论上),与编译器不同,你有时可以使用一个快捷方式,因为你比C语言中表达的更了解情况。

然而,这并不意味着他们做得不好而且代码太慢;只是它比它可能更慢 。它可能不会超过几微秒,但它仍然可能会更慢。

你必须记住的是,编译器执行的一些优化非常复杂:激进的优化往往会导致非常难以理解的汇编代码,如果你手动执行这些代码就很难推理出代码。 。这就是为什么你通常首先用C语言(或其他语言)编写它,然后对其进行分析以找到问题区域,然后继续手动优化该段代码直到它达到可接受的速度 - 因为写入的成本装配中的所有东西都要高得多,而且通常几乎没有任何好处。

答案 6 :(得分:3)

这取决于。英特尔的C编译器现在做得很好。我对ARM的编译器印象不深 - 我可以很容易地编写一个内部循环的汇编版本,执行速度提高了两倍。 您通常不需要在x86计算机上进行组装。如果您想直接访问SSE指令,请查看编译器内在函数!

答案 7 :(得分:2)

实际上,在许多情况下,C可能比汇编更快,因为编译器会对代码应用优化。即便如此,性能差异(如果有的话)可以忽略不计。

我会更专注于可读性和安全性。 C代码库的可维护性,以及C语言是否支持您要执行的操作。在许多情况下,汇编将允许您执行C语言无法执行的更多低级操作。例如,使用汇编,您可以直接利用MMX或SSE指令。

所以最后,关注你想要完成的事情。请记住 - 汇编语言代码维护起来很糟糕。只有在别无选择时才使用它。

答案 8 :(得分:2)

不,编译器根本不会做坏事。对于大多数程序而言,使用汇编可以挤出的优化量是微不足道的。

这个数量取决于你如何定义'现代C编译器'。一个全新的编译器(对于刚刚进入市场的芯片)可能会有大量的低效率,随着时间的推移会被解决。只需编译一些简单的程序(例如string.h函数),并分析每行代码的作用。您可能会对未经测试的C编译器所做的一些浪费事情感到惊讶,并通过简单的代码读取来识别错误。一个成熟的,经过良好测试,经过彻底优化的编译器(Think x86)可以很好地生成程序集,尽管新的程序集仍然可以做得很好。

在任何情况下,C都不能比汇编做得更好。你可以只对两者进行基准测试,如果你的程序集较慢,用-S编译并提交生成的程序集,你就是保证平局。 C被编译为汇编,与字节码具有1:1的相关性。假设已发布完整的指令集,计算机无法执行程序集无法执行的任何操作。

在某些情况下,C的表达力不足以进行全面优化。程序员可能对数据的本质有所了解,这些数据无法用C语言表达,编译器可以这样做利用这些知识。当然,C具有表现力且接近金属,非常适合优化,但并不总是能够完全优化。

编译器无法像人类一样定义“性能”。我知道你说过琐碎的程序,但即使是最简单(有用)的算法,也会在大小和速度。编译器不能以比-Os / -O [1-3]标志更精细的规模执行此操作,但是人类可以知道在程序目的的上下文中“最佳”意味着什么。

某些依赖于体系结构的汇编指令无法用C表示。这是ASM()语句的用武之地。有时候,这些都不是用于优化,而只是因为没有在C中表示该行必须使用原子测试和设置操作,或者我们想用编码参数X发出SVC中断的方式。

尽管如此,C在编程和掌握方面的效率要高出几个数量级。如果性能很重要,那么组装的分析将是必要的,并且可能会找到优化,但是开发人员时间和精力的权衡很少值得为PC上的复杂程序付出努力。对于非常简单的程序,必须尽可能快(如RTOS),或者有严重的内存限制(如带有1KB Flash(不可写)内存的ATTiny和64B RAM),组装可能是唯一的方法去吧。

答案 9 :(得分:1)

考虑到无限的时间和对现代CPU如何工作的非常深刻的理解,您实际上可以编写“完美”程序(即该机器上可能的最佳性能),但您必须考虑,对于您的任何指令程序,CPU在该上下文中的行为方式,流水线操作和缓存相关的优化以及许多其他方面。 构建编译器以生成可能的最佳汇编代码。您很少会理解现代编译器生成的汇编代码,因为它往往非常极端。 有时候编制者在这项任务中失败了,因为他们无法总是预见到正在发生的事情。 一般来说,他们做得很好但有时会失败......

恢复......知道C和汇编绝对不足以在99.99%的情况下比编译器做得更好,并且认为用C编程可以比编写相同汇编程序快10000倍的方法花一些时间来优化编译器在剩下的0.01%中做错了什么,而不是重新发明轮子。

答案 10 :(得分:0)

这取决于您使用的编译器?这不是C或任何语言的属性。从理论上讲,可以加载一个具有如此复杂AI的编译器,您可以将编译序列编译为比GCC对C更高效的机器语言。

这取决于编译器的100%和C的0%。

重要的是C被编写为一种语言, easy 从C编写优化编译器 - >装配,这意味着冯·诺依曼机器的指令。这取决于目标,像prolog这样的某些语言可能更容易在假设的“缩减机器”上进行映射。

但是,鉴于程序集是C编译器的目标语言(技术上可以将C编译为brainfuck或Haskell,没有理论上的区别)然后:

  • 可以在该组件本身(duh)中编写最佳的快速程序
  • 可以编写一个C编译器,它在每个瞬间都能产生最优的汇编。也就是说,每个C程序都存在一个函数,以便在汇编中获得相同的I / O,这个函数是可计算的,尽管可能没有确定性。
  • 世界上所有其他编程语言也可以这样做。