我有一个系统,它生成决策树并将它们转换为嵌套的Common Lisp if语句,其中谓词检查变量值是否为 =或 =给定的整数,例如 (LAMBDA (V1 V2) (IF (= V1 2) (IF (= V1 3) (IF (= V2 3) (IF (= V2 2) 16 (IF (= V2 1) 6
(LAMBDA (V1 V2) (IF (>= V1 2) (IF (<= V1 3) (IF (<= V2 3) (IF (>= V2 2) 16 (IF (>= V2 1) 6 0)) (IF (<= V2 4) 10 0)) (IF (<= V1 4) (IF (>= V2 1) (IF (<= V2 3) 6 0) 0) 0)) (IF (>= V1 1) (IF (>= V2 2) (IF (<= V2 4) 10 0) 0) 0)))
然后我使用eval编译Lisp代码,生成比解释原始决策树快得多的函数.尽管如此,这个编译步骤需要花费相当长的时间:具有5000个嵌套ifs的函数需要花费一分钟来编译(在powerbook上的Clozure Common Lisp中),即使生成if语句需要大约100毫秒.为什么这么简单的结构需要这么长时间?有什么我可以做的大幅加快,一些声明可能吗?我非常感谢您提供的任何指示.
编译函数的实际可移植函数称为COMPILE.您可以告诉Common Lisp编译器通过低优化质量为速度,空间,调试和编译速度投入更少的工作 – 这是否有任何影响取决于实现.
Clozure CL编译器通常不是最亮的编译器,但速度相对较快.一般来说,我认为编译器维护者可能会为您提供更多提示,以加快编译速度.一般来说,我会寻找三个
>告诉编译器做更少的工作:没有类型推断,没有代码优化,没有生成调试信息,没有节省空间,…
>如果有必要告诉编译器它必须推断的东西 – 比如编译器的类型推断,而不是在代码生成期间声明所有类型.但这意味着您实际上需要从类型声明中获得一些优势,例如增加运行时安全性或代码优化.
>编译器本身可能具有速度惩罚,这可能取决于源代码的大小.例如,如果它是二次的,如果我们将代码大小加倍,则编译时间将增加四.只有编译维护者可能知道在这些情况下该做什么 – 也许他们需要实现更有效的数据结构或类似的….
下一个选项是使用Lisp解释器.它们通常只有非常少的定义时间开销 – 但代码通常在运行时运行得慢得多.在某些问题域中,可能遵循混合方法:编译不经常更改的代码并解释经常更改的代码.