性能算法 - 排序 - 树(数据结构)唯一的解决方案?

时间:2012-03-16 12:10:07

标签: algorithm

我手边有一个问题,乍一看它看起来很简单,但是我正在寻找其他解决方案(可能更容易):

表达式:

V0
V1
V2
V3
V4
SumA = V1 + V2
SumB = SumA + V3
SumC = SumB + SumA
SumD = SumC + V0

正如我们在这里看到的,“基础”变量是V0, V1, V2, V3 and V4(每个变量的值都是从DB查询中返回的)

用户要求软件返回V1SumC的结果。

我知道的解决方案:

找到所有必要的变量:V1,SumC,SumB,SumA,V3,V2

对于性能,我只想处理每个变量的数学,只需一次。

这意味着我需要将“基本表达式”中的表达式排序为“顶部变量”。

此时我只看到“树(数据结构)”类型的解决方案>获取V1,V2和V3 然后在得到SumB之后获得SumA,并且最后得到SumC。

还有其他方法可以解决这个问题吗?

该算法的最终目标是使用更复杂的变量和几个“中间变量”。因此,性能至关重要,我无法进行相同的数学运算超过1次。

4 个答案:

答案 0 :(得分:2)

我不确定我完全理解 - 但我认为你指的是common subexpression elimination,[或类似的东西]这是一个非常常见的compiler optimization

执行此优化的一种常用方法是使用程序中表达式的图形[实际上是DAG],并迭代添加新表达式。 DAG中的“源”都是初始变量[示例中为V0,V1,V2,V3,V4]。如果你已经计算过,你可以“知道”哪个表达式是多余的 - 并且避免重新计算它。

These lecture notes似乎是一个不错的更详细的解释[虽然我承认我没有全部阅读]

答案 1 :(得分:1)

首先,您需要构建一个包含所有表达式的树。对于这种情况,树是最简单的数据结构。

现在让我们假设你有这些公式:

SumA = v1 + v2
SumB = v1 + v2 + v3
SumC = ...

并且用户要求SumB(因此您知道 如何计算SumC,但为了让用户满意,您不必)。

在记忆中,看起来像这样:

SumA = Add( v1, v2 )
SumB = Add( Add( v1, v2 ), v3 ) )

下一步是定义比较运算符,它判断两个子树是否相同。运行这些,您会注意到Add( v1, v2 )出现两次,因此您可以优化:

SumA = Add( v1, v2 )
SumB = Add( SumA, v3 )

这意味着您可以通过最少的计算来实现结果。下一步是向操作员添加缓存:当有人询问他们的值时,他们应该缓存它,以便下一个getValue()调用可以返回最后的结果。

这意味着评估SumASumB将填充SumA的缓存。由于您从未要求SumC的值,因此它从未计算过,因此无需任何费用。

答案 2 :(得分:0)

只有加快速度的方法是在级别上使用序列化,除非使用自己的硬件,否则无法以编程方式进行。例: enter image description here

请忽略右上方的注释,这是从我的脚本中窃取的:)

案例A: 100 * 4周期

案例B: 第一个结果需要3个周期,每个周期只需1个(序列化,福特工厂就好)。 - 102个周期

102 vs 400 - 速度约为4 *。

现代CPU可以在某种程度上自动执行此操作,但测量它非常困难。 我听说ICC(intel C编译器)确实优化了它的程序集以尽可能地利用它,也许这部分是为什么他们击败了intel CPU上的所有其他东西:)

答案 3 :(得分:0)

也许你可以简化它并消除中间步骤:

SumA = (V1 + V2)*2
SumC = V3 + SumA