【问题标题】:Common Lisp, asdf, tests, compile system with different optimization levelsCommon Lisp、asdf、测试、编译不同优化级别的系统
【发布时间】:2018-01-25 13:37:49
【问题描述】:

我真正想要的是源内测试定义:

假设我有一个 asdf 系统:

(defsystem simple-system
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-stubs")
                         (:file "2-code") ...))))

还有另一个系统来测试第一个:

(defsystem simple-system-tests
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-real")
                         (:file "2-code") ...))))

它们之间的唯一区别是simple-system 中有1-tests-stubs,而simple-system-tests 中有1-tests-real。 在1-tests-stubs 中,我定义了一个宏(defmacro def-test (&rest _args) nil),它在1-tests-real 中获得了一个“真正的”实现。

现在我想编译 simple-system(declare (optimize (safety 0) (debug 0) (speed 3)))simple-system-tests 和相反的 (declare (optimize (safety 3) (debug 3) (speed 0)))

我该怎么做(在哪里放置以及如何以通用方式为这两个系统设置这些声明)?

如何在simple-system-tests 中重用simple-system 的定义(而不是重复自己重新键入所有模块/组件)?

而且我必须确保所有文件都针对每个系统使用不同的优化级别重新编译。

另外,如果每个系统文件只有在它们被更改时才会重新编译(每个系统的编译文件的自己的副本?)。

【问题讨论】:

    标签: optimization common-lisp asdf


    【解决方案1】:

     优化级别

    你可以试试:around-compile:

    (defsystem simple-system
      :serial t
      :around-compile (lambda (next)
                        (proclaim '(optimize (debug 3) 
                                             (safety 3)
                                             (debug 3)
                                             (speed 0)))
                        (funcall next))
      :components ((:module "src"
                            :components
                            (...))))
    

    文档说(强调我的):

    使用这个钩子可以实现以下效果:本地重命名包,绑定*readtables*和其他语法控制变量,处理警告和其他条件,声明一致的优化设置,节省代码覆盖率信息,维护有关编译时间的元数据,设置 gensym 计数器和 PRNG 种子以及其他非确定性来源,覆盖源位置和/或时间戳系统,检查某些编译时副作用是否适当平衡等。

    该操作是围绕系统中正在编译的每个文件执行的;您可以为模块中的所有文件或特定文件隐藏:around-compile 的值。

    【讨论】:

      【解决方案2】:

      我希望这只是一个错字,在这些示例中,同一个文件 0-package 由两个系统共享。如果不是,你会输得很惨,都是你的错。

      【讨论】:

      • > 同一个文件0-package被两个系统共享​​>
      【解决方案3】:

      安全性低的优化。

      通常我建议像这样以零安全性编译整个系统(库或应用程序):

      (declare (optimize (safety 0) (debug 0) (speed 3)))
      

      将零安全性与类型声明结合使用可能会改变程序的语义,并且错误可能会使程序崩溃。它甚至可能会打开安全漏洞。

      我对生产代码的建议是这样的:

      • 使用 speed = 3 优化速度关键部件,并保留通常的安全设置(2 或 3)。

      • 如果需要低安全设置以进一步提高速度,请仅在需要时声明。 Common Lisp 提供了函数局部声明以及一个特殊的运算符locally,可以进一步限制应用声明的代码区域。

      使优化设置可变

      * (defparameter *safety* 0)
      

      这不起作用,因为安全值需要是数字:

      *SAFETY*
      * (defun foo (a) (declare (optimize (safety *safety*))) (1+ a))
      ; in: DEFUN FOO
      ;     (OPTIMIZE (SAFETY *SAFETY*))
      ; 
      ; caught WARNING:
      ;   Ignoring bad optimization value *SAFETY* in: (OPTIMIZE (SAFETY *SAFETY*))
      ; 
      ; compilation unit finished
      ;   caught 1 WARNING condition
      
      FOO
      

      但这有效,使用读取时评估:

      * (defun foo (a) (declare (optimize (safety #.*safety*))) (1+ a))
      WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
      
      FOO
      

      也可以插入整个声明:

      * (defparameter *optimization-declaration* '(declare (optimize (safety 0))))
      
      *OPTIMIZATION-DECLARATION*
      * (defun foo (a) #.*optimization-declaration* (1+ a))
      WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
      
      FOO
      * 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-27
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 2016-03-18
        • 1970-01-01
        • 1970-01-01
        • 2012-05-23
        相关资源
        最近更新 更多