Optimization 确定哪些变量在什么情况下是常量

Optimization 确定哪些变量在什么情况下是常量,optimization,runtime,jit,Optimization,Runtime,Jit,这个想法有点类似。我想让它更一般一点 基本上,我想为一些特定的情况提供一些专门的和优化的代码变体 换句话说:我已经给出了一个函数的算法/代码(设B={0,1}) 现在,我用一个函数(它预先定义了f的部分输入)指定了一个特殊情况 预先定义的数量(∈ {0..n})然后由 pn := |preset⁻¹({0,1})| 我们现在得到了一个特殊的函数 f_preset : B^(n-pn) -> B^m 同样,我们得到了这个特殊函数的代码/算法。当然,f_预设的代码将比pn>0的f快一些。然

这个想法有点类似。我想让它更一般一点

基本上,我想为一些特定的情况提供一些专门的和优化的代码变体

换句话说:我已经给出了一个函数的算法/代码(设B={0,1})

现在,我用一个函数(它预先定义了f的部分输入)指定了一个特殊情况

预先定义的数量(∈ {0..n})然后由

pn := |preset⁻¹({0,1})|
我们现在得到了一个特殊的函数

f_preset : B^(n-pn) -> B^m
同样,我们得到了这个特殊函数的代码/算法。当然,f_预设的代码将比pn>0的f快一些。然后,您还可以进一步优化此代码(现在可能有一些死代码,一些循环现在可以解包,一些计算可以预先计算,等等)。在某些情况下,它可以有显著的改进

苹果在OpenGL堆栈中大致做到了这一点(据我所知):在为不再改变的变量设置好所有内容后,他们尝试在运行时找到一个好的预设,然后制作专门函数的优化版本,只使用该函数而不是原始函数

最初,我想了一种优化自己游戏的物理模拟的方法。在那里我有很多粒子对象和一组粒子类型(在编译时是未知的)。粒子类型是一组属性。粒子类型在加载后是固定不变的。每个粒子对象都属于Y粒子类型之一。粒子对象的物理模拟是一些非常复杂的代码,有许多分支,并且在很大程度上取决于粒子类型。我现在的想法是为每种粒子类型提供优化的物理模拟功能

在考虑了一下之后,我想再进一步:

我想在运行时自动计算一组这样的预设,并为每个预设维护优化的代码。我想在环境变化时自动添加或删除预设

现在有几个问题:

  • 有没有一个简单的方法来计算一个好的预设?如何知道给定情况下哪些变量是常量
  • 有没有一种简单的方法来检查预设有多好?”“良好”是指结果优化代码的性能
  • 如何比较两种算法/代码的性能?通过一些启发?还是通过随机输入测试
  • 一个功能应该有多少预设(和优化的代码变体)?所有功能的固定限制?还是每个函数都不同?它甚至可能取决于当前的计算机状态吗
  • 如何维护不同的优化代码变体?围绕f的包装函数自动选择最佳优化变量似乎不是很好,因为这可能不是每个调用都需要的简单检查。这个问题的解决方案也可能与如何找到好的预设集/数量的问题密切相关。(在粒子类型的情况下,优化代码将与粒子类型一起附加/保存。粒子类型的数量还定义了预设的数量。)
对于我最初的情况,这些问题中的大多数都有点过时了,但我现在真的对如何以一种更普遍的方式做到这一点感兴趣。当然,大多数/所有这些问题也是无法计算的,但我想知道你在多大程度上仍然可以得到好的结果

整个主题对于JIT编译器中的优化也非常重要。他们已经在做这种优化了吗?到什么程度


最近有没有好的研究成果回答了我的一些问题?或者也可能有一些结果表明,以这样一种普遍的方式做这件事太难了?

在我看来,你是在问这个问题

事实上,我对这个概念有点问题,因为它通常是用过于学术化和过于困难的术语表达的

它通常的表达方式是,您有一些通用函数
F(Islow,Ifast)
,其参数可以在不同的时间采用不同的值。
Islow
参数很少更改,每次调用时,
Ifast
参数可能会不同

然后问题是编写某种部分求值函数
G(F,Islow)->F1(Ifast)
,它接受函数
F
Islow
参数,并生成一个新的(更简单的)函数
F1
,该函数只接受
Ifast
参数

问题是1)必须有人编写通用函数
F
,2)必须有人编写通用部分求值器
G

对我来说,更有意义的是从头开始编写一个函数
H(Islow)->F1(Ifast)
,也就是说,专门为
F1
编写一个代码生成器,而不是编写两个函数
F
G
,特别是在
G
很难编写的情况下

H
通常比
F
容易编写,而且
G
根本不需要编写!结果函数
F1
通常比
F
更小,性能更高,因此这是一个双赢的局面


当人们编写代码生成器时,他们就是这么做的,这是一种非常有效的编程技术。

苹果公司所做的是一种非常明智的技术,已经在图形和其他领域使用了几十年(但我所知从未教过)。例如,贝尔实验室的Blit终端()就使用了这种技术。他们可以生成机器语言并在堆栈上运行。谢谢你提供的信息!不过,这并不是我想要的。我不想被迫先生成专门的版本来调用函数。如果我要保留g,我也不想手工做决定
pn := |preset⁻¹({0,1})|
f_preset : B^(n-pn) -> B^m