gpt4 book ai didi

common-lisp - Common Lisp SBCL 循环性能调整

转载 作者:行者123 更新时间:2023-12-01 07:50:15 25 4
gpt4 key购买 nike

我正在使用 Project Euler 问题 5 蛮力方法来测试性能调整 CL 代码。我是这门语言的新手,想知道如何做这些事情。我写了一个 C 实现,运行时间大约为 1.3 秒。我最初的、幼稚的 CL 实现在大约 15 秒内运行。

这是我的初始 CL 代码

(defpackage :problem-5
(:use #:cl)
(:export :divides-even-p
:has-all-divisors
:smallest-multiple)
)

(in-package :problem-5)

(defun divides-even-p (num divisor)
(= 0 (rem num divisor))
)

(defun has-all-divisors (num start stop)
(loop for divisor from start to stop do
(cond
((not (divides-even-p num divisor)) (return-from has-all-divisors nil))
)
(+ divisor 1)
)
t
)

(defun smallest-multiple (n)
(do ((multiple 1 (+ multiple 1)))
((has-all-divisors multiple 1 n) (format t "~A" multiple))
))

(time (smallest-multiple 20))

到目前为止,我读到的技巧是 1) 优化速度和安全性,2) 内联函数和 3) 显式设置变量类型。应用这些东西,我得到以下代码
(defpackage :problem-5
(:use #:cl)
(:export :divides-even-p
:has-all-divisors
:smallest-multiple)
)

(in-package :problem-5)

(declaim (optimize (speed 3) (safety 0))
(inline divides-even-p)
(inline has-all-divisors)
)

(defun divides-even-p (num divisor)
(declare (type integer num divisor))

(zerop (rem num divisor))
)

(defun has-all-divisors (num start stop)
(declare (type integer num start stop))

(loop for divisor of-type integer from start to stop do
(cond
((not (divides-even-p num divisor)) (return-from has-all-divisors nil))
)
)
t
)

(defun smallest-multiple ()
(do ((multiple 1 (+ multiple 1)))
((has-all-divisors multiple 2 20) (format t "~A" multiple))
))

(time (smallest-multiple))

现在当我运行那个版本时,它运行 7 秒而不是 15. 2 倍的速度,所以在正确的方向上。还有什么办法可以加快速度?对我来说最引人注目的是最小倍数的 do 循环。一方面,我不知道如何为多个变量指定类型。你是怎样做的?有没有更好的方法来做可以产生更少代码的开放式循环?您将如何尝试从这里提高性能? C 代码运行时间约为 1.3 秒,因此我很乐意将其缩短到 2 或 3 秒。

最佳答案

其一,您可以使用 fixnum而不是 integer .后者包含所有整数,前者仅那些适合机器字减去几个标记位(通常约为 61 或 62 位)的整数。
do 中的声明循环出现在正文的开头:

(do ((m 1 (1+ m)))
((has-all-divisors m 2 20)
m)
(declare (fixnum m)))

您也可以使用 loop这里:
(loop :for m :of-type fixnum :upfrom 1
:when (has-all-divisors m 2 20)
:do (return m))

代码改进:
  • 请不要像剪指甲一样留下括号。
  • 使用 if对于两个分支条件。
  • Loop有一个 always关键词:
    (loop :for divisor :of-type fixnum :from start :to stop
    :always (divides-even-p num divisor))
  • 关于common-lisp - Common Lisp SBCL 循环性能调整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56641223/

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