在C/C++程序中使用Assembler优化某些功能真的值得吗?

Par*_*ial 12 c c++ optimization assembly

在诸如游戏开发,实时系统等的某些开发领域中,具有快速且优化的程序是重要的.另一方面,现代编译器已经进行了大量优化,并且在一个需要考虑截止日期的世界中,在汇编中进行优化可能非常耗时.

问题:

  1. 在C/C++程序中使用Assembly优化某些功能真的值得吗?

  2. 使用今天的现代编译器使用Assembly优化C/C++程序时,是否真的有足够的性能提升?


我对所发布的答案有所了解,在嵌入式系统,多媒体编程(图形,声音等)等特定领域,任何可以获得的收益都很重要.此外,人们需要能够(或有能力)在装配中做得比现代编译器更好.做一些真正优化的C/C++可以花费更少的时间并且可以做得足够好.最后一点,学习汇编可以帮助理解程序的内部机制,并最终使某人成为更好的程序员.

Boo*_*jum 27

我说这不值得.我从事可以进行实时3D渲染的软件(即无需GPU辅助渲染).我大量使用SSE编译器内在函数 - 很多丑陋的代码__mm_add_ps()和朋友填充- 但我不需要在很长一段时间内在汇编中重新编写函数.

我的经验是,优秀的现代优化编译器在复杂的微观级别优化方面非常有效.他们将进行复杂的循环变换,例如重新排序,展开,流水线,阻塞,平铺,干扰,裂变等.他们将安排指令以保持管道填充,矢量化简单的循环,并部署一些有趣的位笨拙的黑客.现代编译器是令人难以置信的迷人野兽.

你能打败他们吗?嗯,当然,鉴于他们选择通过启发式方法使用的优化,他们有时会遇到错误.但我发现通过查看更大的图片来优化代码本身要好得多.我是否以最缓存友好的方式布置我的数据结构?我是否正在做一些非正统的误导编译器的事情?我可以重写一些东西给编译器更好的提示吗?我最好重新计算一些东西而不是存储它吗?可以插入预取帮助吗?我在某处有虚假的缓存共享吗?是否存在编译器认为不安全的小代码优化,但在这里是可以的(例如,将除法转换为乘以倒数)?

我喜欢使用编译器而不是反对它.让它处理微观级别优化,以便您可以专注于中级优化.重要的是要好好了解编译器的工作原理,以便了解两个层次之间的界限.


cle*_*tus 10

唯一可能的答案是:是的,如果有相关且有用的性能增益.

我应该猜到的问题是:在C/C++程序中使用汇编语言可以获得有意义的性能提升吗?

答案是肯定的.

你在哪里得到一个案件有意义的性能提升可能已经减弱,在过去10 - 20年的库和编译器有所改善,但对于像86在某些应用中特别手工优化的体系结构(特别是图形相关)可以做到这一点.

但是就像任何东西都不需要优化一样.

我认为,在绝大多数情况下,算法优化和编写高效C(特别是)将创建更多的性能增益,花费的时间少于汇编语言中的重写.

  • 手动编码的好处归结为具有可变长度指令的x86,更重要的是,具有可变数量循环的指令.在优化程序员时,可能知道将确定编译器无法或不会计算出的实际循环数的事情,因此,使编译器无法做出可提高性能的决策.然而,大部分时间它都相当边缘化. (2认同)

Jam*_*ack 6

难点在于,鉴于现代cpu的架构,你能比编译器做得更好吗?如果您正在为简单的cpu(例如嵌入式系统)进行设计,那么您可以进行合理的优化,但是,对于流水线架构,优化要困难得多,因为您需要了解流水线的工作原理.

所以,考虑到这一点,如果你可以做这个优化,并且你正在研究探测器告诉你的东西太慢,并且它是应该尽可能快的一部分,那么是优化是有意义的.

  • 因为它们太便宜了.:)和无聊的傻坐着等待工作来. (2认同)

Dig*_*oss 5

也许

这完全取决于个人计划

在您知道之前,您需要一个配置文件,您可以使用配置文件工具获得该配置文件.有些程序花费所有时间等待数据库,或者他们只是在一个小区域中没有集中运行时.没有它,组装没有多大帮助.

根据经验,90%的运行时发生在10%的代码中.你真的想要一个非常强烈的瓶颈,并不是每个程序都有这个.

此外,这些机器现在如此之快,以至于编程器和CPU内核已经吃掉了一些低悬的水果.例如,假设您编写的代码比编译器更好,并将指令数减半.即使这样,如果你最终做了相同数量的内存引用,如果它们是瓶颈,你也许不会赢.

当然,您可以在之前的循环迭代中开始预加载寄存器,但编译器可能已经尝试过了.

学习汇编作为一种理解机器实际内容的方式非常重要,而不是作为击败编译器的方法.但试一试!