如何说服 Lisp SBCL 进行内联 Fixnum 算术?

2024-05-23

我在其他 SO 答案中找到了一些技术,但显然我无法说服 SBCL 进行内联修复数算术:

(declaim (optimize (speed 2) (safety 1)))

(declaim (ftype (function (fixnum fixnum) double-float) fixnumtest) (inline fixnumtest))
(defun fixnumtest (i j)
  (declare (type fixnum i j))
  (let* ((n (the fixnum (+ i j)))
         (n+1 (the fixnum (1+ n))))
    (declare (type fixnum n n+1))
    (/ 1.0d0 (the fixnum (* n n+1)) )
  )
)

(defun main () 
  (format t "~11,9F~%" (fixnumtest 2 3))
) 

:结果是forced to do GENERIC-* (cost 30)

我还应该尝试什么?

$ sbcl --eval '(load (compile-file "play.lisp"))'
This is SBCL 1.5.1,
…
; compiling file "/opt/tmp/play.lisp" (written 16 OCT 2019 08:03:15 PM):
; compiling (DECLAIM (OPTIMIZE # ...))
; compiling (DECLAIM (FTYPE # ...) ...)
; compiling (DEFUN FIXNUMTEST ...)
; file: /opt/tmp/play.lisp
; in: DEFUN FIXNUMTEST
;     (* N N+1)
; 
; note: forced to do GENERIC-* (cost 30)
;       unable to do inline fixnum arithmetic (cost 4) because:
;       The result is a (VALUES
;                        (INTEGER -21267647932558653961849226946058125312
;                         21267647932558653961849226946058125312)
;                        &OPTIONAL), not a (VALUES FIXNUM &REST T).
;       unable to do inline (signed-byte 64) arithmetic (cost 5) because:
;       The result is a (VALUES
;                        (INTEGER -21267647932558653961849226946058125312
;                         21267647932558653961849226946058125312)
;                        &OPTIONAL), not a (VALUES (SIGNED-BYTE 64) &REST T).
;       etc.

另外,我的想法是否正确doing float to pointer coercion (cost 13)是从函数返回浮点数的常见结果吗?

;     (DEFUN FIXNUMTEST (I J)
;       (DECLARE (TYPE FIXNUM I J))
;       (LET* ((N (THE FIXNUM #)) (N+1 (THE FIXNUM #)))
;         (DECLARE (TYPE FIXNUM N N+1))
;         (/ 1.0d0 (THE FIXNUM (* N N+1)))))
; --> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA 
; ==>
;   #'(SB-INT:NAMED-LAMBDA FIXNUMTEST
;         (I J)
;       (DECLARE (SB-C::TOP-LEVEL-FORM))
;       (DECLARE (TYPE FIXNUM I J))
;       (BLOCK FIXNUMTEST
;         (LET* ((N #) (N+1 #))
;           (DECLARE (TYPE FIXNUM N N+1))
;           (/ 1.0d0 (THE FIXNUM #)))))
; 
; note: doing float to pointer coercion (cost 13) to "<return value>"

好吧,编译器正在告诉你答案,也许是以一种有点无益的方式。如果您有两个修复编号,则情况并非如此,例如,将它们相加会产生修复编号:类型fixnum在算术运算下不封闭(甚至在+, - and *, 不考虑/).

来自SBCL手册 http://www.sbcl.org/manual/#Declarations-as-Assertions:

SBCL 编译器处理类型声明的方式与大多数其他 Lisp 编译器不同。在默认编译策略下,编译器不会盲目相信类型声明,而是认为它们是关于应该检查的程序的断言:所有尚未被证明始终有效的类型声明都会在运行时断言。

如果你想编译机器算术,你需要做的是告诉编译器它正在使用的类型足够好,它可以知道结果类型足够好,可以立即表示。

给定函数中的算术,并假设 64 位实现,那么一个好的类型是(signed-byte 31): 使用起来很诱人(signed-byte 32)但这失败了,因为你最终得到的东西比(signed-byte 64).

因此,除了在返回时使用最终的双浮点数之外,此代码不会发出警告:

(deftype smallish-integer (&optional (bits 31))
  `(signed-byte ,bits))


(declaim (ftype (function (smallish-integer smallish-integer) double-float)
                fixnumtest)
         (inline fixnumtest))

(defun fixnumtest (i j)
  (declare (optimize (speed 2)))
  (declare (type smallish-integer i j))
  (let* ((n (+ i j))
         (n+1 (1+ n)))
    (/ 1.0d0 (* n n+1))))

值得注意的是,一个(signed-byte 64)比 a 大很多fixnum:这没关系,因为在函数内,编译器可以处理适合寄存器的数字,即使它们比fixnums大。

我对 x64 汇编器不太熟悉,无法检查所有算术是否都编译为机器指令,但看起来确实如此。

也许可以说服 SBCL 编译器,让其相信您并不关心获得正确答案,它应该只执行机器算术,即使它知道可能会溢出。我不知道该怎么做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何说服 Lisp SBCL 进行内联 Fixnum 算术? 的相关文章

  • 为什么我应该使用内联代码? [复制]

    这个问题在这里已经有答案了 我是一名 C C 开发人员 这里有几个始终困扰我的问题 常规 代码和内联代码之间有很大区别吗 主要区别是什么 内联代码只是宏的一种 形式 吗 选择内联代码时必须进行什么样的权衡 Thanks 表现 正如之前的答案
  • 优化 tribool 数组的空间

    让我从一些背景开始 通过 tribool 我理解一个可以保存以下值之一的变量 true false or null 有问题复制整数数组与布尔指针数组 https stackoverflow com questions 4350041 cop
  • 删除大量记录需要很长时间

    我有一个包含约 60 000 行的数据库表 在 SQL Server 2012 Express 上运行 我使用以下代码来清除旧行 Deleting CPU measurements older than oldestAllowedTime
  • 将代码保存在 L1 缓存中

    我一直在阅读维基百科关于 K 编程语言的文章 http en wikipedia org wiki K programming language Performance characteristics这就是我所看到的 解释器的小尺寸和语言的
  • R 中 optim() 的优化(L-BFGS-B 需要“fn”的有限值)

    我在 R 中使用 optim 来求解涉及积分的可能性时遇到一些问题 我收到一条错误消息 optim par c 0 1 0 1 LLL method L BFGS B lower c 0 L BFGS B 需要 fn 的有限值 中的错误 下
  • Lisp 中的十进制到二进制 - 制作非嵌套列表

    当达到我的递归情况时 我使用list将未来结果附加到当前结果 但由于递归 我最终得到一个嵌套列表 当我有一个导致递归超过五次的数字时 这会导致错误 任何想法如何我可以在一个简单的非嵌套列表中获得结果 例如 CL 用户 100 8 gt BI
  • L-BFGS 是否有 tf.keras.optimizers 实现?

    有人有 L BFGS 算法的 Tensorflow 2 tf keras 子类吗 如果想使用 L BFGS 目前有两个 官方 选项 TF概率 SciPy 优化 这两个选项使用起来相当麻烦 尤其是在使用自定义模型时 因此 我计划实现 tf k
  • lmfit模型拟合然后预测

    我正在领养lmfit进行曲线拟合并使用拟合模型进行预测 然而下面的代码并没有达到我想要的效果 能否请你帮忙 谢谢 import numpy as np from lmfit import Model def linearModel x a0
  • 如何优化这个查询(涉及4毫米表)

    我正在使用如下所示的遗留数据库架构 product table表有字段 uid 整数 主键 name varchar 50 category表有字段 uid 整数 主键 name varchar 50 好吧 现在product table与
  • 在 VB6 中计时函数/测量性能的最佳方法是什么?

    如果我只想快速测量特定函数花费的时间 我可以调用什么来获得准确的计时 鉴于VB6计时函数精度不高 是否可以调用Windows API函数 您还通过哪些其他方式衡量应用程序性能 有推荐的第三方工具吗 我通常使用 Windows 高分辨率性能计
  • EASTL 与 STL 相比,std::vector::operator[] 怎么会有这么大的性能差异

    根据http www open std org jtc1 sc22 wg21 docs papers 2007 n2271 html http www open std org jtc1 sc22 wg21 docs papers 2007
  • 如何在 Lisp 中生成一系列佩尔数而不是特定的数

    如何使用 cons 或其他方式打印列表佩尔数 https en wikipedia org wiki Pell number直到第N个数 defun pellse k if or zerop k k 1 k 2 pellse k 1 pel
  • 最大化数组中成对距离的总和

    想象一个清单 e1 e2 en 和一个函数f e1 e2 gt number返回常数时间内任意两个元素之间的距离 f e e 0 e1 e2 gt f e1 e2 gt 0 f e1 e2 lt f e1 e3 f e3 e2 目标是排列列
  • iPhone - dequeueReusableCellWithIdentifier 用法

    我正在开发一个 iPhone 应用程序 它有一个相当大的 UITableView 其中的数据来自网络 所以我正在尝试优化它的创建和使用 我发现dequeueReusableCellWithIdentifier非常有用 但是在看到很多使用它的
  • MSVC 可能/不太可能等效

    GCC 编译器支持 builtin expect 语句 用于定义可能和不可能的宏 eg define likely expr builtin expect expr 1 define unlikely expr builtin expect
  • 可以通过Data.Function.fix来表达变形吗?

    我有这个可爱的fixana这里的函数执行速度比她的姐妹快 5 倍左右ana 我有一个criterion报告支持我这一点 ana alg Fix fmap ana alg alg fixana alg fix f gt Fix fmap f
  • LISP 非常简单的列表问题

    我正在学习 lisp 而且我对此还很陌生 所以我想知道 如果我这样做 defparameter list 1 list 1 2 defparameter list 2 list 2 3 defparameter list 3 append
  • 如何加快编辑距离计算速度

    我正在尝试运行模拟来测试平均值编辑距离 http en wikipedia org wiki Levenshtein distance之间随机 二进制字符串 我的程序是用 python 编写的 但我正在使用这个C扩展 https githu
  • 使用实际值检查 cvxpy 中的约束是否正确

    在 cvxpy 中解决优化问题时 是否有一种好方法可以通过用实际值替换优化变量来检查约束是否有效 我有一个复杂的优化问题 100 多个约束 但我知道最佳解决方案应该是什么 但是 cvxpy 失败并显示错误消息ValueError Rank
  • 如何在 Visual Studio Code 上运行 Scheme?

    我想知道如何在 Visual Studio Code 上运行简单的方案代码 我已经安装了一个名为 Scheme 的扩展 但下一步是什么 我没有找到有关如何运行代码或开发人员联系方式的扩展的任何详细信息 现在在 VSCode 上编译Schem

随机推荐