gpt4 book ai didi

common-lisp - 普通口齿不清 : Optimizing functions in SBCL

转载 作者:行者123 更新时间:2023-12-04 03:16:56 25 4
gpt4 key购买 nike

对于 2D 图形,我需要优化我的函数,但在 SBCL 中,我收到很多关于 SBCL 无法内联算术运算的评论。我尝试了各种声明,但似乎并没有让编译器满意。这是一个简单的例子:

(defun test-floor (x div)
(declare (type single-float x)
(type (signed-byte 64) div)
(optimize (speed 3)))
(floor x div))

在下面给出以下 4 个注释。我完全迷失了,因为 #'floor 是一个内置函数。我试图找到有关如何在 SBCL 中正确提供编译器提示的信息/教程,但没有找到正确的信息,因此非常感谢任何信息!不幸的是,Common Lisp 中的优化对我来说是完全未知的领域。我在 Linux 机器上使用 SBCL 1.3.20。

; file: /tmp/file595dqU
; in: defun test-floor
; (FLOOR CL-FLOCKS::X CL-FLOCKS::DIV)
; --> MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL TRUNCATE LET*
; ==>
; (SB-KERNEL:%UNARY-TRUNCATE/SINGLE-FLOAT (/ SB-C::X SB-C::F))
;
; note: forced to do full call
; unable to do inline float truncate (cost 5) because:
; The result is a (values integer &optional), not a (values
; (signed-byte 64) &rest
; t).

; --> MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL TRUNCATE LET* VALUES - *
; ==>
; (SB-KERNEL:%SINGLE-FLOAT SB-C::RES)
;
; note: forced to do full call
; unable to do inline float coercion (cost 5) because:
; The first argument is a integer, not a (signed-byte 64).

; --> MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL FUNCTION IF VALUES 1-
; ==>
; (- SB-C::TRU 1)
;
; note: forced to do generic-- (cost 10)
; unable to do inline fixnum arithmetic (cost 1) because:
; The first argument is a integer, not a fixnum.
; The result is a (values integer &optional), not a (values fixnum &rest t).
; unable to do inline fixnum arithmetic (cost 2) because:
; The first argument is a integer, not a fixnum.
; The result is a (values integer &optional), not a (values fixnum &rest t).
; etc.

; --> MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL FUNCTION IF VALUES
; ==>
; (+ REM SB-C::DIVISOR)
;
; note: doing signed word to integer coercion (cost 20) from div, for:
; the second argument of generic-+
;
; compilation unit finished
; printed 4 notes

CL-USER>

最佳答案

当您调用 floor 时,您必须处理不同的数字子类型:代码将 float 除以整数(可能涉及将整数强制转换为 float ),然后必须强制转换结果返回整数。这是必须正确完成的工作量,如果不限制输入类型,您不太可能绕过它。

如果您改为使用 ffloor ,那么主要结果是一个 float (当你真的需要它时,你仍然可以稍后将它舍入为一个整数(例如转换为像素坐标))。以下代码不给出编译说明:

(defun test-floor (x div)
(declare (type single-float x)
(type fixnum div)
(optimize (speed 3)))
(ffloor x div))

您甚至可以将 div 声明为 float,这会将提供适当类型的值(并执行运行时检查)的责任推给调用者。

另请注意,在定义函数之前,您可能应该(declaim (inline test-floor));这很有帮助,因为编译器可以在代码中放置快捷方式以避免检查输入参数类型和装箱结果。

编辑:

float 的范围覆盖了一个很大的可能域(由于指数):在零附近更密集,更接近无穷大。整数值是线性间隔的,但用相同的位数覆盖较小的范围。所以如果你想保证你的输出适合 fixnum,你必须确保你输入的 float 也不会超出 fixnum 的范围。我尝试了以下方法:

(defun test-round (x)
(declare (type (single-float #.(float most-negative-fixnum 0f0)
#.(float (/ most-positive-fixnum 2) 0f0)) x)
(optimize (speed 3)))
(round x))

我必须将 float 范围的上限减半,因为当您测试时:

(typep (round (coerce most-positive-fixnum 'single-float)) 'fixnum)

...它返回 NIL。我没有太多时间了解为什么会发生这种情况,但这取决于您的实现和体系结构。取最正 fixnum 的一半可确保该值足够低以转换为 fixnum。现在,我没有更多的编译笔记了。

(同样适用于(signed-byte 64)))

注意。与上面的示例不同,您应该使用 deftype 并避免在各处重复相同的声明。

关于common-lisp - 普通口齿不清 : Optimizing functions in SBCL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47634578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com