You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:49:56