如果我在现代C ++中使用GCC 4.7和VS12等现代编译器进行内联汇编,我现在有什么好处?例如。矢量化和一些小优化?或者它只是顽皮,现代优化编译器在任何范围内使用它都没有给我什么?
答案 0 :(得分:3)
内联汇编的使用使您的代码体系结构具体化。即使对于像vectorization
这样的事情,您现在依赖于执行此代码的目标需要支持这些特殊/增强指令集的事实。
让我们说如果有人试图将您的代码从x86
移植到ARM
,他们就会遇到困难。
我建议有一种机制,通过该机制,您可以检测目标是否支持SSE2或SSE3等矢量指令集并执行优化的代码,并且具有一个故障安全代码,该代码在目标上运行。 t支持增强的指令集。
例如,Linux内核抽象了arch
目录下的所有体系结构特定代码,并且针对不同的体系结构存在相同功能的实现。如果您知道您的代码可能在多个不同的体系结构上执行,那么您可以通过提出自己的抽象来做类似的事情。
答案 1 :(得分:2)
与许多事情一样,这取决于。
对于您可能编写的大多数代码,内联汇编不太可能有用。现代编译器相当聪明,并且通常会生成至少与您可以编写的任何内容一样好的代码。 (而且它们的生成速度也比你编写和调试的速度快得多。)
正如您所猜测的那样,例外情况是编写某些矢量代码。虽然有些编译器会尝试对某些循环进行矢量化,但它们并不像熟练技术人员那样做得好。在某些应用中(例如,DSP,视频编码等),这可以产生显着差异。但是,这需要详细了解您正在编写的处理器 - 编写错误的矢量代码通常会比编译器提出的标量代码更糟糕!
结论:除非你有充分的理由相信你需要来编写内联汇编,否则请避免使用它。
答案 2 :(得分:1)
一般来说,您正在寻找的内在函数可以精确地包装特定指令。
这可让您访问例如向量指令不放弃C ++的类型安全性,同时保留与内联汇编提供的类似程度的控制。本质上,使用内在函数,您可以选择要使用的指令,但编译器会执行寄存器分配。
答案 3 :(得分:0)
对此的回答有点像英文表达“一段弦长多久” - 如果不实际展开整段琴弦就不能轻易回答。同样在这里,不知道代码实际应该做什么,很难说是否有好处。
我的一般方法是使用C或C ++编写代码,然后查看编译器的功能。如果它足够快[无论定义为什么],那么就没有必要做任何其他事情了。如果速度不足,那么看一下代码,看看是否有任何简单的算法优化,或简化,拆分函数以避免代码中间的if语句等等。配置代码,看看哪里它正在花时间。
在每一步改进之后[测量,并跟踪变化,设置等 - 我通常都有电子表格,数据为“有了这个变化,它的运行速度提高了4%”,“有了这个,它跑了2%慢“。
一旦你用尽所有其他选项,那么你就可以开始考虑内联汇编程序了。有时,如果你“做正确的事”,可能会有很大的改进。在其他时候,根本没有太大的收获。
我最近使用gcc
编写了一些内存基准测试。当我使用volatile
(强制内存写入实际发生)时,编译器生成相当垃圾代码,所以当我在内联汇编程序中编写相应的代码时,它的速度提高了3-4倍。但是,一旦我重新安排代码实际上在内存写入本身后的一个步骤中使用写入内存,并删除了volatile
,编译器就像我的SSE2代码一样好。
对于复杂的SSE代码,我仍然认为编译器在某些情况下缺少一点点,但有时它可能非常聪明 - 它肯定优化了简单的循环到完整的SSE2代码。
我发现的最大收获是当编译器根本无法理解您实际想要发生的事情时[或者它无法为您想要的操作生成正确的代码]。非时间移动就是这方面的一个例子 - 你不想在缓存中存储某些东西,因为你知道它无论如何都不会在缓存中有用。