什么静态编译器可以优化,而JIT无法优化?

3

静态编译器在优化方面有哪些示例,而JIT无法完成优化的一些C++编译器优化呢?

5个回答

9

没有。证明:拿任何编译器并将其用作JIT即可。QED。

然而,JIT在执行时间上受到限制,因此不适合进行复杂的优化。


2
@Thomas:尝试并不能证明在考虑到每种语言、编译器、平台、优化等组合的情况下都是正确的。因此,尝试并不能证明什么。请参见证明 - Yakov Galka
2
当然可以。这个“证明”是正确的。而且已经有LLVM可以存储其中间形式,并在运行时执行它可以在编译时执行的所有优化。 - Axel Gneiting
@Axel:实际上,IR并不是完全优化的形式。有后端转换器可以接受IR并针对最终架构进行优化(取决于其指令集)。@ybungalobill:我认为你抓住了JIT最重要的问题,因为它必须“快”,所以在优化方面不能做太多工作。 - Matthieu M.

2

这个答案列出了JIT优化器使用的优化和策略。它们与本地代码优化器所做的并没有根本上的不同。

Jitter中的一个限制是它不能花费大量时间分析代码。每毫秒都会影响程序的响应能力。有两种策略可以帮助解决这个问题。程序集可以通过ngen.exe进行预编译,所有.NET程序集都是这样做的,对于您自己的程序集也最好这样做。只要它们“较大”,可能花费在jitting代码上的时间就比在磁盘上查找和加载.ni.dll文件要少。

Jitter会在方法开始执行之前按需编译代码。这往往会将成本分摊到时间上,与在人类时间运行的代码相关,这时响应能力很重要。

值得注意的一个细节是,Jitter可以利用特定于核心的指令。这是一个基本消失的优势,现在的核心并没有那么不同。但它会在x64操作系统上轻松生成64位代码,而无需进行任何特殊处理。

一个经常提到的数字是,被JIT编译的机器代码效率相当于本地预编译代码的85%。但要注意源代码的质量和性质永远是第一位的。


1
通常情况下,静态编译器可以做到的事情,即时(JIT)编译器也可以做到 - 因为 JIT 编译器具有与等效的静态编译器相同甚至更多的信息。 JIT 编译器有一个巨大的优势 - 它知道代码将在哪个环境中运行。
由于语言特性,C++ 可能具有的某些特定优化在 C# 中可能不存在。但同样可能反过来 - 在没有指针的情况下,更容易推理出 C#。
在考虑 C# 优化时,大部分优化发生在从 C# 到 IL 的转换过程中,而不是 JIT 中。

1
我不确定最后一段的理由是什么。几乎所有的优化都不是由C#编译器完成的。C#编译器的优化器相当弱。有关详细信息,请参见http://blogs.msdn.com/b/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx。 - Eric Lippert
我以为我在某个地方读到过这个 - 但当然我被纠正了。 - James Gaunt
@Eric: C# 编译器优化能力较弱,这是有意为之吗?我不知道在早期引入优化的后果是什么,所以这样做是为了确保您不会在以后无法更改的情况下进行优化吗?比如说,计划在合适的时候一次性引入各种优化(比如在出现某些突破时)。 - Joan Venge
1
@Joan:简单来说,Jitter可以做得更好。请记住,C#编译器只是输出IL代码。考虑一种优化,比如内联。我们不知道机器码的大小,也不知道在实际处理器上额外调用与额外缓存未命中的成本;没有这样的信息,我们就无法知道内联一块IL代码是否是一个好主意,所以我们甚至不会尝试。许多优化涉及寄存器调度;而IL甚至没有寄存器的概念。等等。 - Eric Lippert
1
@Joan:没错,编译器当然不能假设编译机器与目标机器具有相同的规格!开发人员通常拥有比客户更强大的机器。但总的来说,编译器本身不会根据机器规格改变其行为。IDE 可能会,Visual Studio 作为一个整体可能会。例如,VS 可能会注意到您有一个四核处理器,并决定并行执行构建的 CPU 绑定部分。我不知道 VS 是否这样做或它是如何工作的;那不是我的专业领域。 - Eric Lippert
显示剩余2条评论

1
这里的主要问题是运行时间和资源。编译Visual Studio需要61小时,而我甚至不知道他们使用了什么样的构建机器。然而,JIT必须在机器真实资源的一小部分内并在毫秒级别内运行。他们不可能进行如此强的优化。

1
你是怎么知道需要61小时的信息的?只是好奇。 - Joan Venge
1
@Joan:我不记得了,具体是谁说的。 - Puppy

0
静态编译器在很长时间之前就已经运行,而JIT则是在代码执行之前不久完成。静态编译器有更多的时间来运行,因此需要较长时间才能完成的优化通常由静态编译器完成而不是JIT编译器。原则上,JIT可以进行这些优化,但是执行它们需要额外的时间,使它们不切实际。
另一方面,现代JIT在某些情况下可以对代码做出更激进的假设(产生比静态编译器更快的代码),因为它有选择回退到不太优化的版本的选项,如果这些假设被证明是不正确的。

1
为什么一个静态编译器不能生成检查和后备代码呢? - Karl Knechtel
@Karl:它可以,而且有时候他们会这样做。 - Yakov Galka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接