- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
对于我的一个项目,我使用了很多分支。思考:
if (foo) { do something }
else if (bar) { do something }
else if (bar2) { do something }
... and so on
和
if (foo) { do something }
if (bar) { do something }
if (bar2) { do something }
... and so on
我一直在想的是,进行子表达式和/或逻辑消除以加快速度是否有意义。为了完整起见,您可以假设所有这些都在一个函数中。说,如果 foo
和 bar
有一个共同的子表达式,你可以这样写:
if (commonSubExpr)
{
if (foo without commonSubExpr) { do something }
if (bar without commonSubExpr) { do something }
}
if (bar2) { do something }
... and so on
同样,您可以应用许多简单的 bool 逻辑规则来优化规则。
我的问题是:这样做是否有意义?或者我可以期望 JIT'ter 来处理这个问题吗?
(根据 excellent article by Eric Lippert,除了常量折叠之外,编译器并未对此进行优化 - 我认为情况仍然如此)。
更新+1
好吧,我不应该问这是否有意义,因为现在我有好人试图向我解释什么是过早的优化,这不是我所追求的……我的错误。请假设我知道过度设计、过早优化等问题——这正是我在这里试图避免的。
所以尝试 2...我想知道事情是如何工作的 以及我可以从编译器/JIT'ter 得到什么。
我还注意到一些上下文可能对这里有帮助,所以这里有一些关于应用程序的信息:
在这种情况下,应用程序是一种在运行时使用 Reflection.Emit to IL 编译的领域特定语言。我有充分的理由不能使用现有的语言或现有的编译器。性能很关键,编译后会执行很多操作(这就是为什么首先将其编译为 IL,而不是简单地解释代码)。
我问这个问题的原因是因为我想知道我应该将编译器中的优化器设计到什么程度。如果 JIT'ter 负责消除子表达式,我将设计优化器只做基本的事情,如常量折叠,如果 .NET 希望在编译器中发生这种情况,我将在编译器中设计它。根据我的预期,优化器将具有完全不同的设计。由于分支可能是最重要的性能消耗者,而且实现对我的软件设计有巨大影响,所以我特地决定询问这个问题。
我知道在实现编译器之前没有办法对此进行测试 - 这需要大量工作 - 所以我想在开始实现之前直接了解我的基础知识。我不知道如何测试它的原因是因为我不知道 JIT'ter 在什么情况下优化了哪些代码;我希望 .NET 运行时中的某些触发器会导致某些优化(使测试结果不可靠)...如果您知道解决这个问题的方法,请告诉我。
表达式 foo
, bar
等可以是您通常在代码中看到的任何形式,但您可以假设它是一个函数。所以,它可以是 if (StartDate < EndDate)
的形式, 但不能是类似 if (method1() < method2())
的东西.解释一下:在后一种情况下,编译器不能简单地对方法的返回值做出假设(在优化之前,您需要了解有关返回值的信息),因此子表达式消除一点也不简单。
因此,作为子表达式消除的示例:
if (int1 < int2 && int1 < int3) {
//...
}
else if (int1 < int2 && int1 < int3) {
//...
}
可以重写为:
if (int1 < int2)
{
if (int1 < int3) {
//...
}
else if (int1 < int3) {
//...
}
}
总而言之:我想知道这些子表达式消除优化是否有意义 - 或者它们是否由 JIT'ter 处理。
最佳答案
So, it can be of the form if (StartDate < EndDate)
不,它不能。您的编译器需要生成对 DateTime.op_LessThan()
方法的调用。生成对方法的调用的问题在于您无法 100% 确定该方法不会产生可观察到的副作用。 DateTime.op_LessThan 没有,但这不是您的编译器可以自行找到的东西。您必须在编译器中对该规则进行硬编码。
然而,抖动可以,它确实知道该方法的代码是什么样的。而且它非常小,它会将方法内联到单个 CPU 指令中。其平均执行时间少于一个 CPU 周期。处理器中内置的分支预测逻辑可确保分支不太可能使流水线停滞。
很难让编译器中的优化器产生返回。它只能消除非常简单的代码的公共(public)子表达式,没有副作用,但这样的代码已经运行得非常快了。 C# 编译器是一个值得遵循的好模型,它不会优化并且让工作变得不稳定。 this answer 中描述了抖动执行的优化。 .是的,常见的子表达式消除就是一种它知道如何执行的优化。
然而,它是否应用优化是不可预测的,这取决于它需要在方法中生成哪些其他代码。我没有检查过这个具体案例,我宁愿怀疑它是否会由于分支。如果您还想为 && 和 || 提供短路评估,那么它远不止这些。运营商。您可以找到的唯一方法是查看实际生成的机器代码。选择您要使用平台目标设置验证的抖动。构建测试代码的发布配置。然后Tools + Options,Debugging,General,取消勾选“Suppress JIT optimization”选项。并查看带有断点和 Debug + Windows + Disassembly 的机器码。注意伪造的测试代码,如果抖动可以优化太多,它通常会运行得不切实际。并注意在这上面浪费太多时间:)
关于c# - .NET 编译器中的分支消除与 Jit'ter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18783941/
在动态语言中,动态类型代码 JIT 是如何编译成机器码的?更具体地说:编译器是否会在某个时候推断类型?还是在这些情况下严格解释? 例如,如果我有类似下面的伪代码 def func(arg) i
X86 和 AMD64 是许多计算环境(桌面、服务器和 super 计算机)最重要的架构。显然,JIT 编译器应该同时支持它们才能获得认可。 直到最近,SPARC 架构才是编译器合乎逻辑的下一步,特别
既然有如此多的 JIT 实现,每个 JIT 都会发出 native 代码。那么为什么没有人制作像 JIT2EXE 这样的工具来将 native 代码保存为 native 可执行文件呢? 最佳答案 这个
JIT 编译器将字节码编译成机器码的概念我还是不太清楚。我想知道为什么它比非 JIT 解释器产生更快的代码。有人可以给我一个很好的例子来说明这个过程是如何完成的吗? 最佳答案 假设您有一个需要执行一百
Torchscript 提供了 torch.jit.trace 和 torch.jit.script 将 pytorch 代码从 Eager 模式转换为脚本模型。从文档中,我可以理解 torch.ji
好的,我已经阅读了一些关于 JIT 和非 JIT 启用解释器之间差异的讨论,以及为什么 JIT 通常会提高性能。 但是,我的问题是: 最终,不支持 JIT 的解释器是否必须像 JIT 编译器那样将字节
有没有办法在消除 JIT 开销的同时实现 JIT 性能?最好通过将类文件编译为 native 镜像。 我研究过GCJ,但即使对于简单的程序,GCJ输出的性能也比Java JIT差很多。 最佳答案 您可
我试图更好地理解 JIT 编译器在 volatile 变量值缓存方面如何为 java 工作。考虑这个问题中提出的例子: Infinite loop problem with while loop an
我的代码是这样的: @jit(nopython=True) def sum_fn(arg1, arg2, ...argn): ..... for i in xrange(len(arg
以下代码无效: def get_unique(arr): return jnp.unique(arr) get_unique = jit(get_unique) get_unique(jnp.
我需要能够调用一个 GPU 函数,该函数本身间接调用另一个 GPU 函数: from numba import cuda, jit import numpy as np # GPU function
我有一个关于使用 Continuum 的 Accelerate 和 numba 包中的 Python CUDA 库的问题。正在使用装饰器@jit与 target = gpu同 @cuda.jit ?
有人可以指出我的方向,这可能会让我明白为什么 JIT 会取消优化我的循环? (OSR)。看起来它被 C1 编译一次,然后多次取消优化(我可以看到数十或数百个以 开头的日志) 这是包含该重要循环的类:
我引用了Oracle的以下文档: http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/underst_jit
我需要在 C++ 中运行预训练的 pytorch 神经网络模型(在 python 中训练)来进行预测。 为此,我按照此处给出的有关如何在 C++ 中加载 pytorch 模型的说明进行操作:https
我正在使用 numbas @jit 装饰器在 python 中添加两个 numpy 数组。如果我使用 @jit 与 python 相比,性能是如此之高。 然而,即使我传入 @numba.jit(nop
我是Python新手。 我编写了一些代码尝试将图片混合为新图片。 我完成了,但是浪费了太多时间。 所以我尝试使用 Numba 让代码在我的 GPU 上运行。但遇到一些警告和错误 os Ubuntu 1
我正在将我的网站从安装在共享网络托管帐户(在 DreamHost)上的 PHP v.5 转换为在 PHP 7.3.11 上运行。转换后,我开始注意到偶尔会收到以下警告: Warning: preg_m
在 Stack Overflow 上向所有编译器设计者致以问候。 我目前正在从事一个项目,该项目的重点是开发一种用于高性能计算的新脚本语言。源代码首先被编译成字节码表示。字节码然后由运行时加载,它对其
我相信 Apple 已禁止在 ARM64 架构上同时写入和执行内存,请参阅: 参见 mmap() RWX page on MacOS (ARM64 architecture)? 这使得像 jonesf
我是一名优秀的程序员,十分优秀!