如何加快Common Lisp`IF`语句的编译速度?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何加快Common Lisp`IF`语句的编译速度?相关的知识,希望对你有一定的参考价值。

我有一个系统生成决策树并将它们转换为嵌套的Common Lisp if语句,其中谓词检查变量值是否为>=<=给定的整数,例如:

(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编译器通过低optimize质量为speedspacedebugcompilation-speed投入更少的工作 - 这是否有任何影响取决于实现。

Clozure CL编译器通常不是最亮的编译器,但速度相对较快。一般来说,我认为编译器维护者可能会为您提供更多提示,以加快编译速度。一般来说,我会寻找三个

  1. 告诉编译器做更少的工作:没有类型推断,没有代码优化,没有生成调试信息,没有节省空间,...
  2. 如果有必要告诉编译器它必须推断的东西 - 比如编译器的类型推断,而不是代码生成期间的所有类型。但这意味着您实际上需要从类型声明中获得一些优势,例如增加运行时安全性或代码优化。
  3. 编译器本身可能具有速度惩罚,这可能取决于源代码的大小。例如,如果它是二次的,如果我们将代码大小加倍,则编译时间将增加四。只有编译维护者可能知道在这些情况下该做什么 - 也许他们需要实现更有效的数据结构或类似的....

下一个选项是使用Lisp解释器。它们通常只有非常少的定义时间开销 - 但代码通常在运行时运行得慢得多。在某些问题域中,可能遵循混合方法:编译不经常更改的代码并解释经常更改的代码。

另一答案

你当然可以(declare (optimize (compilation-speed 3))),并可能减少其他品质(见http://clhs.lisp.se/Body/d_optimi.htm#optimize)。

但是,我猜测编译速度慢是由编译器进行的优化引起的,因此结果似乎在执行时可能不会那么快。但也许不是,你必须进行实验。

我还会考虑使用您的领域知识进行哪些优化。对此的提示也可能来自分析生成函数的disassemble的输出。

最后,如果不同值的数量不是太大,也许您可​​以将决策树转换为查找表。

以上是关于如何加快Common Lisp`IF`语句的编译速度?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 common-lisp CLOS 中指向一个 defgeneric 实例

如何理解这个 Common Lisp 包的行为?

如何在 Common Lisp 中增加或减少数字?

Common Lisp 中的本地状态

“我是如何从 Python 换到 Common Lisp,又换到 Julia 的?”

Emacs Lisp 和 Common Lisp 之间的主要区别是啥? [关闭]