【问题标题】:Avoiding float to pointer coercion in Common Lisp在 Common Lisp 中避免浮点到指针强制
【发布时间】:2017-11-23 08:09:51
【问题描述】:

我使用 SBCL(64 位 v1.4.0)进行数值计算。 启用优化后,出现如下编译提示:

note: doing float to pointer coercion (cost 13) to "<return value>"

我使用的代码如下:

(defun add (a b)
  (declare (optimize (speed 3) (safety 0)))
  (declare (double-float a b))
  (the double-float (+ a b)))

我也尝试过ftype 并得到了相同的注释。

另一方面,以下代码不显示注释:

(defun add-fixnum (a b)
  (declare (optimize (speed 3) (safety 0)))
  (declare (fixnum a b))
  (the fixnum (+ a b)))

我认为 double-float 和 fixnum 都是 64 位宽。 为什么 SBCL 不能通过像 C 语言这样的寄存器返回双浮点值?有没有什么办法可以避免浮点到指针强制而无需内联扩展?

【问题讨论】:

标签: optimization double common-lisp


【解决方案1】:

问题在于 Lisp 数据是动态类型的,函数的返回值必须包含类型信息。在大多数实现中,类型标记存储在值的低位中。

这允许对 fixnums 进行特殊优化。它们的类型标签全为零,值是按类型标签中的位数左移的整数。当您添加这些值时,结果中的标记位仍然为零,因此您可以使用正常的 CPU 操作对这些值执行算术运算。

但这不适用于浮点值。执行 CPU 操作后,必须将类型标签添加到值中。这就是“浮点到指针强制”的含义(在许多语言中更常见的词是“装箱”)。

声明返回类型并不能避免这种情况,因为调用者不一定有权访问声明——Lisp 允许您在单独的编译单元中编译调用者,而不是它们调用的函数。

如果你声明了函数INLINE,那么就不需要这样做了,因为调用者知道它返回的类型,硬件值可以直接返回给他们而不需要添加标签。

更详细的解释可以在这个古老的comp.lang.lisp thread中找到。它指的是 CMUCL,它是 SBCL 的来源(注意警告的措辞完全相同)。

【讨论】:

  • 非常感谢!我了解 SBCL 和其他 Common Lisp 解释器上的类型标签规范,并且 fixnum(在 SBCL 上实际上是 62 位宽)的情况很特殊。您对单独编译的解释完全解决了我的问题。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2016-06-20
  • 2018-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
相关资源
最近更新 更多