【问题标题】:defclass type information for performance用于性能的 defclass 类型信息
【发布时间】:2014-04-14 13:03:45
【问题描述】:

在下面的程序中,删除该行

    (declare (type (simple-array bit) arr))

使用 SBCL 使运行时间增加了 3 倍以上。另一方面,defclass 宏中通过:type 提供的类型信息似乎对性能没有影响。

(defclass class-1 () ((arr :type (simple-array bit))))

(defun sample (inst)
  (declare (type class-1 inst))
  (let ((arr (slot-value inst 'arr)))
    (declare (type (simple-array bit) arr)) ;; 3x running time without
    (map-into arr #'(lambda (dummy) (if (< (random 1.0) 0.5) 0 1)) arr)))

(let ((inst (make-instance 'class-1)))
  (setf (slot-value inst 'arr) (make-array 10000 :element-type 'bit))
  (loop for i from 1 to 10000 do (sample inst)))

如何在每次使用时不必将arr 插槽声明为simple-array bit 的情况下获得相同的性能优势?后者特别烦人,因为(据我所知)每次都需要通过let 或类似方式引入绑定;我不能只在需要的地方写(slot-value inst 'arr)

【问题讨论】:

    标签: performance common-lisp sbcl typing clos


    【解决方案1】:

    首先,这是一个特定于 SBCL 的问题,您可能会在 SBCL 用户列表上得到更好的答案。不同的编译器会做不同的优化,并且大多数都会忽略至少一些声明。

    第二次,你应该 let-bind arr 因为你使用了两次。

    第三,如果要避免let-bind,可以使用the

    (the (simple-array bit) (slot-value inst 'arr))
    

    第四,如果希望编译器推断类型,请使用特定的阅读器而不是slot-value

    (defclass c () ((arr :type (simple-array bit) :reader c-arr)))
    
    (defun sample (inst)
      (declare (type class-1 inst))
      (let ((arr (c-arr inst)))
        (map-into arr #'(lambda (dummy) (random 2)) arr)))
    

    c-arr 应该允许编译器更容易地推断值类型,但是(正如您自己发现的那样!)您可能需要声明其返回类型:

    (declaim (ftype (function (c) (simple-array bit)) c-arr))
    

    显然,原因是 SBCL 忽略了槽类型声明。

    【讨论】:

    • 使用阅读器是个好主意,但它对我没有直接作用。然而,起作用的是阅读器加上以下内容,使用您的类和函数名称:(declaim (ftype (function ((c)) (simple-array bit)) c-arr))。有了这个,即使:type(declare (type class-1 inst)) 也可以省略。
    • 应该是(declaim (ftype (function (c) (simple-array bit)) c-arr))。两者似乎都有效,我不知道为什么。以前没用过那个表格。
    【解决方案2】:

    添加类型信息会产生不同的效果,具体取决于您使用的编译器以及生效的优化级别。

    对于优化编译器,它可能如下所示:

    • 没有信息:通用操作,相当快
    • 类型声明可用:添加了在运行时检查此特定类型的操作 -> 较慢
    • 类型声明可用,高度优化和低安全性:在运行时没有添加操作来类型检查,为此类型生成专门的代码 -> 可能更快

    一些编译器也会忽略 CLOS 槽的类型声明。如果他们不这样做,还有两种变体:1)安全意味着添加运行时检查,2)低安全性和高速意味着生成专门的指令

    总结:由于添加了类型检查,类型声明可能会增加运行时开销,而且安全性很高。专用数据类型不一定更快,但安全性低,优化度高。

    【讨论】:

      猜你喜欢
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      相关资源
      最近更新 更多