将函数声明为“内联”的好处?
每次我读到 C 中的“内联”声明时,都会提到它只是一个提示 给编译器(即它不必遵守它)。那么添加它有什么好处,还是我应该依赖编译器比我更了解?
Every time I read about the "inline" declaration in C it is mentioned that it is only a hint to the compiler (i.e. it does not have to obey it). Is there any benefit to adding it then, or should I just rely on the compiler knowing better than me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
使用
inline
关键字有两个原因。一个是优化提示,你可以放心地忽略它;你的编译器也喜欢忽略它。另一个原因是允许一个函数存在于多个翻译单元中,并且这种使用是绝对必要的。例如,如果将函数放入 .h 头文件中,最好将其声明为内联。There are two reasons to use the
inline
keyword. One is an optimization hint, and you can safely ignore it; your compiler is like to ignore it too. The other reason is to allow a function to exist in multiple translation units, and that usage is strictly necessary. If you put a function into a .h header file for example, you'd better declare it inline.编译器很聪明,但仍然可以从开发人员的提示中受益。如果您认为某些函数特别应该内联,那么就这样声明它们。这当然不会造成伤害。
Compilers are smart, but can still benefit from hints from the developer. If you think some of your functions in particular should be inlined, then declare them as such. It certainly doesn't hurt.
一般来说,现代编译器会“内联”他们认为重要的东西。我会让它为你处理。
编辑:
读完别人写的东西后,你知道吗?我想我会让它处理大部分内联,然后分析你的代码,然后是瓶颈的内联函数。我的建议受到与我一起工作的某个开发人员的影响,他预先优化了他的所有代码。有一半的时间我需要花5分钟。只是弄清楚想要完成什么。
Generally modern compilers will "inline" things they deem important. I'd let it handle it for you.
Edit:
After reading what others have written, you know what? I think I'd let it handle most of the inlining THEN profile your code and THEN inline functions which are bottlenecks. My advise is slightly colored by a certain developer I work alongside who pre-optimizes all his code. Half the time I need to spend 5 min. just figuring out what is trying to be accomplished.
就像其他人所说的那样,关键字只是一个提示,但大多数编译器都非常重视它。此外,大多数编译器不擅长内联来自不同编译单元的函数 - 如果您在文件
ac
中定义Foo()
,但在bc
中调用它code>,它智能地内联bc
对Foo()
的调用的可能性相当小。 (事实上,如果没有 LTCG,这种情况根本不会发生。)因此,当您确定某个函数确实需要内联时,就值得使用它。这是最好根据经验时机做出的决定。例如,在我的平台上,我测量了内联函数和直接(非虚拟)函数之间的差异约为 5 纳秒,因此我的经验法则是,我内联函数的周期应少于 10 个:简单的访问器等。当我的探查器告诉我,我在调用它们的开销上浪费了很多时间时,其他特定函数会被内联。
Like everyone else has said, the keyword is only a hint, but it's a hint most compilers take pretty seriously. Also, most compilers are very bad at inlining functions from different compilation units -- if you define
Foo()
in filea.c
, but call it inb.c
, odds are pretty slim that it will intelligently inlineb.c
's calls toFoo()
. (in fact, it won't happen at all without LTCG.) so it's worth using when you're sure a function really needs to be inlined. That's a decision best made with empirical timings.For example, on my platform I measured the difference between an inline and a direct (nonvirtual) function as about 5 nanoseconds, so my rule of thumb is that I inline functions that should take less than ten cycles: trivial accessors and the like. Other specific functions get inlined afterwards when my profiler tells me that I'm wasting a lot of time in the overhead of calling them.
C++ FAQ对此有很好的信息。我更喜欢使用内联函数,因为它为编译器提供了更多关于我“希望”它做什么的信息。编译器最终是否内联它取决于它,但给它一点帮助不会有什么坏处。
The C++ FAQ has good info on this. I prefer to use the inline function as it gives the compiler more information about what I would "like" it to do. Whether or not the compiler ends up inlining it is up to it, but giving it a little help won't hurt.
它为编译器提供了一种简单的机制来应用更多优化。
内联函数速度更快,因为您不需要将参数和返回地址等内容压入/弹出堆栈;但是,它确实会使您的二进制文件稍大一些。
它有显着差异吗?对于大多数人来说,在现代硬件上还不够明显。但它可以带来改变,这对某些人来说已经足够了。
将某些内容标记为内联并不能保证它会内联。这只是给编译器的一个建议。有时这是不可能的,例如当您有虚函数或涉及递归时。有时编译器只是选择不使用它。
我可以看到这样的情况会产生明显的差异:
It provides a simple mechanism for the compiler to apply more OPTIMIZATIONS.
Inline functions are faster because you don't need to push and pop things on/off the stack like parameters and the return address; however, it does make your binary slightly larger.
Does it make a significant difference? Not noticeably enough on modern hardware for most. But it can make a difference, which is enough for some people.
Marking something inline does not give you a guarantee that it will be inline. It's just a suggestion to the compiler. Sometimes it's not possible such as when you have a virtual function, or when there is recursion involved. And sometimes the compiler just chooses not to use it.
I could see a situation like this making a detectable difference:
您不能绝对确定编译器会捕获代码的“关键”部分:当您知道它很重要时,请使用“内联”。
编译器不是分析器。
You can't be absolutely sure the compiler will catch the "critical" sections of your code: use "inline" when you know it matters.
A compiler isn't a profiler.
差异可能并不重要。
保留
inline
直到您测量代码性能并确定可以通过内联编译器选择视为正常的特定函数来获得一些性能。即使这样,也不能保证编译器会内联该函数,但至少你已经做了你能做的一切:)The difference isn't likely to matter.
Leave
inline
out until you measure the code performance and determine that you could gain some performance by inlining a specific function that the compiler chose to treat as normal. Even then, there's no guarantee the compiler will inline that function, but at least you did all you could :)由于它只是对编译器的提示,因此编译器可以自由地忽略它,并且很可能会忽略它。编译器有很多您没有的相关信息,例如循环将占用多少缓存行,并且可以根据具体情况进行内联或不内联。
这只是一个提示,所以使用它不太可能造成任何伤害。几乎可以肯定,您应该避免任何强制函数内联或不内联的特定于编译器的事情。
Since it's only a hint to the compiler, the compiler is free to ignore it, and likely will. The compiler has a lot of relevant information you don't have, such as how much of a cache line a loop will take up, and can inline or not on a case-by-case basis.
It's just a hint, so using it is unlikely to hurt anything. You almost certainly should avoid any compiler-specific things that force functions to be inlined or not inlined.
该声明几乎毫无用处,并且与最初的意图大相径庭。编译器对于内联什么和不内联什么采取了更多的自由(IMO)。
它是对编译器的一个提示,使用它会对您有所帮助,并且只有在某些时候才具有预期的意义。
如果您需要编写性能关键的程序,请不要依赖编译器(性能和优化的知识不是一天就能学会的)。通常有一种方法可以覆盖编译器的判断(而不仅仅是暗示您的偏好),以强制内联。这就是我在 95% 以上的情况下声明内联函数/方法的方式(也知道它何时是隐式的)。如果/当您知道需要知道如何正确内联时,也可以使用强制内联,但一定要了解何时以及如何使用它。
内联并不是提高性能的灵丹妙药。它可能会产生负面影响。在极端情况下,滥用内联可能会产生一些可怕的后果,但如果使用不当,通常性能会更差,并且二进制文件会更大。正确使用内联可以产生相当积极的结果。
内联还有助于删除原本会导出的符号,从而减少二进制文件,具体取决于实例的数量和大小。
另一件事:您将获得与 C++ 不同的链接。
The declaration is pretty much useless and quite different from the original intent. Compilers have taken much more liberty wrt what and what not to inline (IMO).
It's a hint to the compiler, using it will help you and have the intended significance only sometimes.
If you need to write performance critical programs, do not rely on the compiler (knowledge of performance & optimization is not learned in a day). There's usually a way to override the compiler's judgement (not just hint at your preference), to force inlining. This is the way I declare a function/method inline, more than 95% of the time (knowing also when it is implicit). If/When you know you'd need to know how to inline properly, then employ force-inlining as well, but do learn when and how to use it.
Inlining is not a silver bullet to better performance; it can have negative effects. Abuse of inlining can have some scary consequences in extreme cases, but usually performance is a little worse and binaries are larger when used improperly. Proper use of inlining can have considerably positive results.
Inlining is also helpful to remove symbols which would otherwise be exported, reducing the binary, depending on the number of instances and size.
Another thing: You'll get different linkage with C++.