【发布时间】:2018-05-28 20:33:37
【问题描述】:
上下文
我目前正在优化一个用于科学计算的库。我对 Commom Lisp 还很陌生。我使用的功能非常小,大约可以执行。在普通笔记本电脑上为 10 ns 到几百纳秒。性能已经非常接近 C 但我想要我能得到的每一点速度。
我使用 SBCL 及其编译器说明和 (time) 宏进行优化(欢迎任何一般性建议)。我目前正在优化一个单线程计算字符串,该字符串将包含在未来的独立线程中。
问题
为了论证,假设我有一个函数(foo),它逐项添加两个包含 3 个变量的列表。一旦优化,它可能是这样的:
(defun foo (a1 a2 a3 b1 b2 b3)
(declare (optimize (speed 3))
(type double-float a1 a2 a3 b1 b2 b3))
(list (+ a1 b1) (+ a2 b2) (+ a3 b3)))
我会用 :
(time (dotimes (it 1000000 t) (foo 1.0d0 2.0d0 2.351d0 223.0d0 124.2d0 321d0)))
SBCL 笔记
据我所知,编译器抱怨将结果“转换”到列表中很昂贵。
note: doing float to pointer coercion (cost 13)
我想要什么
SBCL 的抱怨似乎是明智的,所以我正在寻找一种方法来消除那些讨厌的列表,无论如何我必须在稍后的某个时候再次剥离这些列表,以便将它们提供给其他计算。我愿意为此走低级并失去(一些)抽象。用例可能如下所示:
(let ((res1 0d0)
(res2 0d0)
(res3 0d0))
(declare (type double-float res1 res2 res3))
(magic-abstraction-I-want res1 res2 res3 (foo 1d0 1d0 1d0 1d0 1d0 1d0)))
有了这个,我可以用最少或不存在的开销进行字符串计算,只做需要的计算,而不用花时间创建列表或访问它们。
我尝试了什么/想尝试什么
内联
我看到在简单函数(例如 foo)上的性能大幅提升:
(declaim (inline foo))
据我了解,它有点“扩展”函数并在调用它的级别将其内联写入。对吗,它到底是做什么的?这实际上是我想要的吗?它是否以某种方式解决了“投射到列表”的问题?
(另外,如果您从我写的内容中看到我可能误解了某些内容,请随时提供一般的速度优化建议)
编辑:了解values后
我修改了foo,现在是:
(defun foo (a1 a2 a3 b1 b2 b3)
(declare (optimize (speed 3))
(type double-float a1 a2 a3 b1 b2 b3))
(values (+ a1 b1) (+ a2 b2) (+ a3 b3)))
SBCL 仍然输出三个关于强制返回值到指针的注释。而且我仍然在消耗字节,用以下方式衡量:
(time (dotimes (it 1000000 t) (foo 1.0d0 2.0d0 2.351d0 223.0d0 124.2d0 321d0)))
但是,使用inline 的调用要快得多,并且没有任何缺点(我猜是预期的):
(declaim (inline foo))
;;;;
(let ((r1 0d0) (r2 0d0) (r3 0d0)
(a1 1d0) (a2 2d0) (a3 3d0)
(b1 4d0) (b2 5d0) (b3 6d0))
(declare (optimize (speed 3))
(type double-float r1 r2 r3 a1 a2 a3 b1 b2 b3))
(time (dotimes (it 1000000 t) (setf (values r1 r2 r3) (foo a1 a2 a3 b1 b2 b3)))))
性能与完全相同相同:
(let ((r1 0d0) (r2 0d0) (r3 0d0)
(a1 1d0) (a2 2d0) (a3 3d0)
(b1 4d0) (b2 5d0) (b3 6d0))
(declare (optimize (speed 3))
(type double-float r1 r2 r3 a1 a2 a3 b1 b2 b3))
(time (dotimes (it 1000000 t)
(setf r1 (+ a1 b1))
(setf r2 (+ a2 b2))
(setf r3 (+ a3 b3)))))
这正是我想要的。最后一个很次要的事情是SBCL还在抱怨foo的优化,但我只能忍气吞声。
【问题讨论】:
-
@sds:看起来他问的不仅仅是多值问题——问题是关于浮点数的“科学计算”。
-
@RainerJoswig:直接的问题是关于多个值的无约束返回,
values问题回答了这个问题。关于科学计算的次要、更高级的问题应该在单独的问题中或在对这个问题进行大量编辑后更具体地提出。 -
虽然这个问题的一阶答案是“观察到
values存在”,但我认为这个问题与values的问题不重复。具体来说,仍然会遇到具有多个值的浮点到指针强制问题,并且该问题的答案与此完全无关。在foo2中也存在与未引用相关的理解问题,假设编译良好,仅测量函数调用的开销。关于ftype声明还有一些话要说。 -
@DanRobertson:如果 OP 对
values有足够的了解,可以适当地编辑问题——这样它就不再是一个骗子——我很乐意重新打开它。 -
好的,我根据您对
values的建议编辑了我的问题。这证明是我想要的。谢谢大家。
标签: floating-point common-lisp inline sbcl multiple-value