Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为性能定义类类型信息_Performance_Common Lisp_Sbcl_Typing_Clos - Fatal编程技术网

Performance 为性能定义类类型信息

Performance 为性能定义类类型信息,performance,common-lisp,sbcl,typing,clos,Performance,Common Lisp,Sbcl,Typing,Clos,在以下程序中,删除该行 (declare (type (simple-array bit) arr)) 使用SBCL使运行时间增加3倍以上。另一方面,通过:type在defclass宏中给出的类型信息似乎对性能没有影响 (defclass class-1 () ((arr :type (simple-array bit)))) (defun sample (inst) (declare (type class-1 inst)) (let ((arr (slot-value i

在以下程序中,删除该行

    (declare (type (simple-array bit) arr))
使用SBCL使运行时间增加3倍以上。另一方面,通过
:type
defclass
宏中给出的类型信息似乎对性能没有影响

(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)))
(defclass class-1()((arr:type(简单数组位)))
(除样品(仪器)
(申报(1类仪表)
(let((arr(槽值指令arr)))
(声明(类型(简单数组位)arr));;3倍的运行时间
(映射到arr#’(lambda(虚拟)(if(<(随机1.0)0.5)0 1))arr)
(让((inst(使实例'class-1'))
(setf(插槽值inst'arr)(使数组为10000:元素类型'bit))
(从1到10000 do的i循环(样本仪器)))

如何在每次使用时都不必声明
arr
插槽a
简单数组位
的情况下获得相同的性能优势?后者尤其令人讨厌,因为(据我所知)每次都需要通过
let
或类似方式引入绑定;我不能只在需要的地方写
(slot value inst'arr)

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

第二次,您应该让bind
arr
,因为您要使用它两次

第三个,如果要避免让绑定,可以使用:

(the (simple-array bit) (slot-value inst 'arr))
第四个,如果希望编译器推断类型,请使用特定读取器,而不是
插槽值

(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忽略了插槽类型声明。

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

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

  • 无信息:通用操作,速度相当快
  • 类型声明可用:添加了在运行时检查此特定类型的操作->较慢
  • 类型声明可用,高优化和低安全性:运行时没有添加类型检查操作,为该类型生成专门的代码->可能更快
一些编译器还忽略CLOS插槽的类型声明。如果没有,则又有两种变体:1)安全意味着添加运行时检查,2)低安全和高速意味着生成专门的指令


摘要:由于添加了类型检查,类型声明可能会增加具有高安全性的运行时开销。专门的数据类型不一定更快,安全性低,优化程度高。

使用读卡器是一个好主意,但它不能直接用于我。然而,使用您的类和函数名,读卡器加上以下各项才有效:
(declaim(ftype(function((c))(简单数组位))c-arr))
。有了它,甚至可以省略
:type
,以及
(declare(type class-1 inst))
。它可能应该是
(declaim(ftype(function(c)(简单数组位))c-arr))
。两者似乎都起作用,我不知道为什么。我以前没用过那个表格。