Jas*_*ick 33 c macros optimization performance inline
我在Stack Overflow中搜索了类似函数的宏与内联函数的优缺点.
我发现了以下讨论: C中不同宏函数/内联方法的优缺点
......但它没有回答我的主要问题.
也就是说,在内存使用和执行速度方面,使用宏函数(带有变量,可能还有其他函数调用)和内联函数的开销是多少?
开销中是否存在编译器相关的差异?我同时拥有icc和gcc.
我模块化的代码片段是:
double AttractiveTerm = pow(SigmaSquared/RadialDistanceSquared,3);
double RepulsiveTerm = AttractiveTerm * AttractiveTerm;
EnergyContribution +=
4 * Epsilon * (RepulsiveTerm - AttractiveTerm);
Run Code Online (Sandbox Code Playgroud)
我将其转换为内联函数/宏的原因是我可以将其放入ac文件中,然后有条件地编译其他类似但略有不同的函数/宏.
例如:
double AttractiveTerm = pow(SigmaSquared/RadialDistanceSquared,3);
double RepulsiveTerm = pow(SigmaSquared/RadialDistanceSquared,9);
EnergyContribution +=
4 * Epsilon * (RepulsiveTerm - AttractiveTerm);
Run Code Online (Sandbox Code Playgroud)
(注意第二行的差异......)
这个函数是我的代码的核心功能,在我的程序中每步调用数千次,我的程序执行数百万步.因此,我希望尽可能减少开销,因此我浪费时间来担心内联的转换,将代码转换为宏.
根据之前的讨论,我已经意识到宏的其他优点/缺点(类型独立性和由此产生的错误)...但我最想知道的,目前不知道的是性能.
我知道你们中的一些C老兵会对我有一些很好的见解!
Ste*_*non 24
调用内联函数可能会也可能不会生成函数调用,这通常会产生非常少量的开销.inline函数实际内联的确切情况因编译器而异; 大多数人都努力内联小函数(至少在启用优化时),但并不要求它们这样做(C99,§6.7.4):
使函数成为内联函数表明对函数的调用尽可能快.这些建议有效的程度是实施定义的.
宏不太可能产生这样的开销(尽管如此,几乎没有什么可以防止编译器以某种方式做某事;标准没有定义什么机器代码程序必须扩展到,只有编译程序的可观察行为).
使用更干净的东西.轮廓.如果重要,做一些不同的事情.
还有,fizzer说的是什么; 对pow(和division)的调用通常都比函数调用开销更昂贵.尽量减少这些是一个好的开始:
double ratio = SigmaSquared/RadialDistanceSquared;
double AttractiveTerm = ratio*ratio*ratio;
EnergyContribution += 4 * Epsilon * AttractiveTerm * (AttractiveTerm - 1.0);
Run Code Online (Sandbox Code Playgroud)
是EnergyContribution由仅是这个样子条款?如果是这样,拉4 * Epsilon出来,每次迭代保存两次乘法:
double ratio = SigmaSquared/RadialDistanceSquared;
double AttractiveTerm = ratio*ratio*ratio;
EnergyContribution += AttractiveTerm * (AttractiveTerm - 1.0);
// later, once you've done all of those terms...
EnergyContribution *= 4 * Epsilon;
Run Code Online (Sandbox Code Playgroud)
Has*_*yed 10
宏并不是真正的功能.无论你定义什么,宏都会在编译器看到它之前通过预处理器逐字地发布到你的代码中.预处理器只是一个软件工程师工具,可以使各种抽象更好地构建代码.
内联函数或编译器确实知道的函数,并且可以决定如何处理它.用户支持的inline关键字只是一个建议,编译器可能会覆盖它.正是这种超越,在大多数情况下会产生更好的代码.
编译器了解这些函数的另一个副作用是,您可能会强制编译器做出某些决定 - 例如,禁用内联代码,这可以使您更好地调试或分析代码.可能有许多其他用例,内联函数启用与宏.
虽然宏非常强大,但为了支持这一点,我会引用谷歌测试和谷歌模拟.使用宏的原因有很多:D.
使用函数链接在一起的简单数学运算通常由编译器内联,特别是如果函数仅在转换步骤中调用一次.因此,无论天气如何提供,编译器都会为您做出内联决策,我不会感到惊讶.
但是,如果编译器没有,您可以手动平掉代码段.如果你把它弄平,也许宏可以作为一个很好的抽象,毕竟它们提供了与"真实"函数类似的语义.
紧要关头
那么,您是否希望编译器知道某些逻辑边界,以便它可以生成更好的物理代码,或者您是否希望通过手动或使用宏将其展平来对编译器进行强制决策.该行业倾向于前者.
在这种情况下,我倾向于使用宏,只是因为它快速而肮脏,而不必学习更多东西.但是,由于宏是软件工程抽象,并且因为您关注编译器生成的代码,如果问题变得稍微高级,我会使用C++模板,因为它们是为您正在考虑的问题而设计的.
这是你要消除的对pow()的调用.此函数采用一般浮点指数,并且无法提升到整数指数.用例如替换这些调用
inline double cube(double x)
{
return x * x * x;
}
Run Code Online (Sandbox Code Playgroud)
是唯一会对你的表现产生重大影响的事情.