在发布模式下编译时,大量嵌套循环会导致链接器无休止地运行吗?
我正在 VS2010 发布模式下编译一个非常小的 Win32 命令行应用程序,并打开所有速度优化(不是内存优化)。
该应用程序旨在服务于单一目的 - 执行单个预定义的复杂数学运算以找到特定问题的复杂解决方案。该算法功能齐全(已确认),并且在调试模式下编译和运行良好。但是,当我在发布模式下编译时(算法足够大,可以利用优化),Link.exe 似乎会无限运行,并且代码永远不会完成链接。它的 CPU 使用率为 100%,内存使用率没有变化 (43,232 K)。
我的应用程序仅包含两个类,它们都是非常短的代码文件。然而,该算法包含 20 个左右的嵌套循环,每层内都有内联函数调用。链接器是否尝试运行这些循环中的所有可能路径?如果是这样,为什么调试模式链接器没有任何问题?
这是一个小型命令行应用程序(2KB exe 文件),编译时间不会超过几分钟。我已经等了30分钟了,没有任何变化。我正在考虑让它在一夜之间链接,但如果它真的试图运行算法中所有可能的代码路径,它可能会在没有方便的超级计算机的情况下链接数十年。
我需要做什么才能让链接器摆脱这个无限循环?此类代码是否有可能创建无限链接循环而不会在链接周期之前出现编译器错误?
编辑:
Jerry Coffin 指出我应该杀死链接器并再次尝试。我忘了在原来的帖子中提到这一点,但我已经中止了构建,关闭并重新打开了 VS,并尝试构建多次。问题是一致的,但到目前为止我还没有更改任何链接器选项。
编辑2:
我还忽略了我删除了“Debug”和“Release”文件夹并从头开始重新构建的事实。相同的结果。
编辑3:
我刚刚确认关闭函数内联会使链接器正常运行。问题是我需要函数内联,因为这是一个对性能非常敏感的操作,内存占用最小。这让我想问,为什么内联会导致出现这样的问题?
编辑4:
在无休止的链接周期中显示的输出:
Link:
Generating code
EDIT5:
我确认将所有代码放入一个 CPP 文件中并不能解决问题。
I'm compiling a very small Win32 command-line application in VS2010 Release-Mode, with all speed optimizations turned on (not memory optimizations).
This application is designed to serve a single purpose - to perform a single pre-defined complex mathematical operation to find a complex solution to a specific problem. The algorithm is completely functional (confirmed) and it compiles and runs fine in Debug-Mode. However, when I compile in Release-Mode (the algorithm is large enough to make use of the optimizations), Link.exe appears to run endlessly, and the code never finishes linking. It sits at 100% CPU usage, with no changes in memory usage (43,232 K).
My application contains only two classes, both of which are pretty short code files. However, the algorithm comprises 20 or so nested loops with inline function calls from within each layer. Is the linker attempting to run though every possible path through these loops? And if so, why is the Debug-Mode linker not having any problems?
This is a tiny command-line application (2KB exe file), and compiling shouldn't take more than a couple minutes. I've waited 30 minutes so far, with no change. I'm thinking about letting it link overnight, but if it really is trying to run through all possible code paths in the algorithm it could end up linking for decades without a SuperComputer handy.
What do I need to do to get the linker out of this endless cycle? Is it possible for such code to create an infinite link-loop without getting a compiler-error prior to the link cycle?
EDIT:
Jerry Coffin pointed out that I should kill the linker and attempt again. I forgot to mention this in the original post, but I have aborted the build, closed and re-opened VS, and attempted to build multiple times. The issue is consistent, but I haven't changed any linker options as of yet.
EDIT2:
I also neglected to mention the fact that I deleted the "Debug" and "Release" folders and re-built from scratch. Same results.
EDIT3:
I just confirmed that turning off function inlining causes the linker to function normally. The problem is I need function inlining, as this is a very performance-sensitive operataion with a minimal memory footprint. This leads me to ask, why would inlining cause such a problem to occur?
EDIT4:
The output that displays during the unending link cycle:
Link:
Generating code
EDIT5:
I confirmed that placing all the code into a single CPP file did not resolve the issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
嵌套循环仅在链接时间代码生成方面影响链接器。有大量的选项决定了它的详细工作方式。
首先,我建议完全禁用 LTCG,看看是否存在其他异常问题。
如果它在禁用 LTCG 的发布中链接良好,您可以尝试内联限制、内在函数和优化级别。
Nested loops only affect the linker in terms of Link Time Code Generation. There's tons of options that determine how this works in detail.
For a start I suggest disabling LTCG alltogether to see if there's some other unusual problem.
If it links fine in Release with LTCG disabled you can experiment with inlining limits, intrinsics and optimization level.
您是否进行了重建?如果其中一个目标文件或 .ilk 文件损坏(尽管发布模式可能未使用其中之一,但我无法确定您的项目设置),那么重建所做的清理过程应该可以修复它。
仅当调试(或图形设计器之一)保持构建产品的打开句柄时,关闭并重新打开 Visual Studio 才有用。
这就引出了另一个建议——检查任务管理器并确保您没有仍在运行的应用程序的副本。
Have you done a rebuild? If one of the object files got corrupted, or a .ilk file (though release mode probably isn't using one, I can't be sure about your project settings), then the cleaning pass which rebuild does should cure it.
Closing and re-opening Visual Studio is only helpful in cases when the debugging (or one of the graphical designers) is keeping an open handle to the build product.
Which leads to another suggestion -- check Task Manager and make sure that you don't have a copy of your application still running.
如果链接器似乎是瓶颈并且两个类都很短,为什么不将所有代码放在一个文件中呢?此外,在 Visual Studio 中的项目设置对话框中的 C++ 常规选项卡下有一个多处理器编译选项。这两者都可能有帮助。
If the linker seems to be the bottle neck and both classes are pretty short, why not put all the code in a single file? Also, there is a multi-processor compilation option in visual studio under C++ general tab in the project settings dialog box. Both of these might help.
一些选定的答案:
调试版本不内联。一点也不。这使得可以在所有函数中放置断点。 。
链接器是否真正运行无限循环,或者是否正在评估 2^20 个不同的内联/非内联组合并不重要 后者仍然可能需要 2^20 秒。 (我们知道链接器是从“生成代码”消息中内联的)。
你为什么要使用 LTCG?对于这么小的项目,将所有内容都放在一个 .cpp 文件中是完全可行的。目前,编译器只是解析 C++,并没有生成任何代码。这也解释了为什么它没有任何问题:编译器中只有一个循环,遍及所有源代码行。
Some selected answers:
Debug builds don't inline. Not at all. This makes it possible to put breakpoints in all functions. It wou
It doesn't really matter whether the linker truly runs an infinite loop, or whether it is evaluating 2^20 different combinations of inline/don't inline. The latter still could take 2^20 seconds. (We know the linker is inlining from the "Generating code" message).
Why are you using LTCG anyway? For such a small project, it's entirely feasible to put everything in one .cpp file. Currently, the compiler is just parsing C++, and not generating any code. That also explains why it doesn't have any problem: there's only a single loop in the compiler, over all lines of source code.
在我的公司,我们发现了类似的事情。
据我所知,这不是无限循环,只是一个很长的操作。
这意味着您必须选择:
您必须决定是否真的需要这些优化。这里程序只是一个小帮手,程序运行23.4秒还是26.8秒并不重要。与构建速度相比,程序速度的提高使得优化几乎毫无用处。至少在我们的特殊场景中是这样。
Here in my company we discovered something similar.
As far as I know it is no endless loop, just a very long operation.
This means you have to options:
You have to decide if you really need these optimizations. Here the program is just a little helper, where it does not matter if the program is running 23.4 seconds or 26.8. The gain of program speed compared to the build speed are making the optimizations nearly useless. At least in our special scenario.
我在尝试构建 OSMesa x64 发布模式时遇到了这个问题。我对本次讨论的贡献是,在让链接器运行一夜之后,它确实正确完成了。
I encountered exactly this problem trying to build OSMesa x64 Release mode. My contribution to this discussion is that after letting the linker run overnight, it did complete properly.