C++ 是否有理由不使用链接时优化 (LTO)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23736507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a reason why not to use link-time optimization (LTO)?
提问by Honza
GCC, MSVC, LLVM, and probably other toolchains have support for link-time (whole program) optimization to allow optimization of calls among compilation units.
GCC、MSVC、LLVM 和可能的其他工具链支持链接时(整个程序)优化,以允许优化编译单元之间的调用。
Is there a reason not to enable this option when compiling production software?
编译生产软件时是否有理由不启用此选项?
采纳答案by Ali
I assume that by "production software"you mean software that you ship to the customers / goes into production. The answers at Why not always use compiler optimization?(kindly pointed out by Mankarse) mostly apply to situations in which you want to debug your code (so the software is still in the development phase -- not in production).
我认为“生产软件”是指您运送给客户/投入生产的软件。在回答为什么不经常使用编译器优化?(Mankarse亲切地指出)主要适用于您想要调试代码的情况(因此该软件仍处于开发阶段——而不是生产阶段)。
6 years have passed since I wrote this answer, and an update is necessary. Back in 2014, the issues were:
自从我写这个答案以来已经过去了 6 年,需要更新。早在2014年,问题是:
- Link time optimization occasionally introduced subtle bugs, see for example Link-time optimization for the kernel. I assume this is less of an issue as of 2020. Safeguard against these kinds of compiler and linker bugs: Have appropriate tests to check the correctness of your software that you are about to ship.
- Increased compile time. There are claims that the situation has significantly improved since 2014, for example thanks to slim objects.
- Large memory usage. This postclaims that the situation has drastically improved in recent years, thanks to partitioning.
- 链接时间优化偶尔会引入一些细微的错误,请参见内核的链接时间优化示例。我认为这在 2020 年不再是一个问题。 防范这些类型的编译器和链接器错误:进行适当的测试以检查您即将发布的软件的正确性。
- 增加编译时间。有人声称这种情况自 2014 年以来已经有了显着改善,例如得益于纤薄的物体。
- 内存使用量大。这篇文章声称,由于分区,近年来情况有了显着改善。
As of 2020, I would try to use LTO by default on any of my projects.
到 2020 年,我将尝试在我的任何项目中默认使用 LTO。
回答by Jeremy
This recent questionraises another possible (but rather specific) case in which LTO may have undesirable effects: if the code in question is instrumented for timing, and separate compilation units have been used to try to preserve the relative ordering of the instrumented and instrumenting statements, then LTO has a good chance of destroying the necessary ordering.
最近的这个问题提出了另一种可能(但相当具体)的情况,在这种情况下,LTO 可能会产生不良影响:如果有问题的代码针对时序进行了检测,并且已使用单独的编译单元来尝试保留检测语句和检测语句的相对顺序,那么 LTO 很有可能破坏必要的排序。
I did say it was specific.
我确实说过它是具体的。
回答by ericcurtin
If you have well written code, it should only be advantageous. You may hit a compiler/linker bug, but this goes for all types of optimisation, this is rare.
如果你的代码写得很好,那应该只是有利的。您可能会遇到编译器/链接器错误,但这适用于所有类型的优化,这种情况很少见。
Biggest downside is it drastically increases link time.
最大的缺点是它大大增加了链接时间。
回答by TruthSeeker
Apart from to this,
除了到这个,
Consider a typical example from embedded system,
考虑一个嵌入式系统的典型例子,
void function1(void) { /*Do something*/} //located at address 0x1000
void function2(void) { /*Do something*/} //located at address 0x1100
void function3(void) { /*Do something*/} //located at address 0x1200
With predefined addressed functions can be called through relative addresses like bellow,
可以通过如下相对地址调用预定义的寻址函数,
(*0x1000)(); //expected to call function2
(*0x1100)(); //expected to call function2
(*0x1200)(); //expected to call function3
LOT can lead to unexpected behavior.
LOT 可能会导致意外行为。
回答by Dirk Herrmann
One scenario where link-time-optimization can lead to unexpected behavior for wrong code is the following:
链接时间优化可能导致错误代码出现意外行为的一种情况如下:
Imagine you have two source files read.c
and client.c
which you compile into separate object files. In the file read.c
there is a function read
that does nothing else than reading from a specific memory address. The content at this address, however, should be marked as volatile
, but unfortunately that was forgotten. From client.c
the function read
is called several times from the same function. Since read
only performs one single read from the address and there is no optimization beyond the boundaries of the read
function, read
will always when called access the respective memory location. Consequently, every time when read
is called from client.c
, the code in client.c
gets a freshly read value from the address, just as if volatile
had been used.
想象一下,你有两个源文件read.c
和client.c
其编译成独立的目标文件。在文件中read.c
有一个函数read
,除了从特定的内存地址读取外,什么都不做。不过这个地址的内容应该标记为volatile
,可惜忘记了。从client.c
该函数read
被调用从相同的功能几次。由于read
仅从地址执行一次单次读取,并且没有超出read
函数边界的优化,read
因此在调用时将始终访问相应的内存位置。因此,每次read
调用 from 时client.c
,中的代码client.c
都会从地址中获取一个新读取的值,就好像volatile
已被使用。
Now, with link-time-optimization, the tiny function read
from read.c
is likely to be inlined whereever it is called from client.c
. Due to the missing volatile
, the compiler will now realize that the code reads several times from the same address, and may therefore optimize away the memory accesses. Consequently, the code starts to behave differently.
现在,通过链接时间优化,无论从哪里调用 from的微小函数read
,read.c
都可能被内联client.c
。由于缺少volatile
,编译器现在将意识到代码从同一地址读取多次,因此可能会优化内存访问。因此,代码开始表现不同。