在SBCL中如何指定#'sqrt函数的返回类型以优化性能?
在SBCL中指定sqrt返回类型以优化浮点运算编译
我在SBCL 2.3.1中启用速度优化编译以下代码:
(defun test (x y) (declare (optimize speed)) (declare (type single-float x y)) (+ x (sqrt y)))
编译时收到以下优化提示:
; processing (DEFUN TEST ...) ; file: /var/tmp/slimeftWp5F ; in: DEFUN TEST ; (SQRT RT-SPEC::Y) ; ; note: unable to ; optimize ; due to type uncertainty: ; The result is a (VALUES (OR (COMPLEX SINGLE-FLOAT) (SINGLE-FLOAT -0.0)) ; &OPTIONAL), not a (VALUES FLOAT &REST T). ; (+ RT-SPEC::X (SQRT RT-SPEC::Y)) ; ; note: forced to do GENERIC-+ (cost 10) ; unable to do inline float arithmetic (cost 2) because: ; The second argument is a (OR (COMPLEX SINGLE-FLOAT) (SINGLE-FLOAT -0.0)), not a SINGLE-FLOAT. ; The result is a (VALUES (OR SINGLE-FLOAT (COMPLEX SINGLE-FLOAT)) ; &OPTIONAL), not a (VALUES SINGLE-FLOAT &OPTIONAL). ; unable to do inline float arithmetic (cost 3) because: ; The second argument is a (OR (COMPLEX SINGLE-FLOAT) (SINGLE-FLOAT -0.0)), not a (COMPLEX ; SINGLE-FLOAT). ; The result is a (VALUES (OR SINGLE-FLOAT (COMPLEX SINGLE-FLOAT)) ; &OPTIONAL), not a (VALUES (COMPLEX SINGLE-FLOAT) ; &OPTIONAL). ; ; compilation unit finished ; printed 2 notes
我知道通用函数#'sqrt可能返回不同类型,但我传入的是single-float类型参数,能不能指定它的返回类型必须是single-float?
解决方法
当然可以,通过以下几种方式可以让编译器确定sqrt的返回类型,从而启用内联浮点运算优化:
用
the操作符明确指定返回类型
直接在sqrt调用处声明返回类型,告诉编译器你保证该调用结果为single-float:(defun test (x y) (declare (optimize speed)) (declare (type single-float x y)) (+ x (the single-float (sqrt y))))注意:这种方式要求你确保输入的
y是非负的single-float,如果y为负,运行时会触发类型不匹配错误。添加运行时断言保证输入合法性
若想同时避免非法输入导致的运行时错误,可以加入assert检查y的范围:(defun test (x y) (declare (optimize speed)) (declare (type single-float x y)) (assert (>= y 0.0s0) (y) "y must be a non-negative single-float") (+ x (the single-float (sqrt y))))使用SBCL特有扩展
sb-ext:assume提供优化提示
如果你不需要运行时检查,仅想给编译器传递优化信息,可以用sb-ext:assume,它不会生成运行时代码:(defun test (x y) (declare (optimize speed)) (declare (type single-float x y)) (sb-ext:assume (>= y 0.0s0)) (+ x (the single-float (sqrt y))))
原理说明
SBCL的sqrt在输入为负的single-float时会返回复数类型,因此编译器无法确定返回类型,只能使用通用的GENERIC-+。通过明确指定返回类型,编译器可以确定运算类型,进而启用更高效的内联浮点运算。
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

