参与计划的论证成本

时间:2013-12-12 13:26:55

标签: scheme argument-passing

我发现了一件有趣的事情。通过论证可能值得考虑,特别是在时间很重要的情况下。代码如下。

(define (collatz-num n)
  (define (collatz-iter n m)
    (cond
     ((= n 1)
      m)
     ((even? n)
      (collatz-iter (/ n 2) (+ m 1)))
     (else
      (collatz-iter (+ (* 3 n) 1) (+ m 1)))))
  (collatz-iter n 1))


(define (collatz-iter n m)
  (cond
   ((= n 1)
    m)
   ((even? n)
    (collatz-iter (/ n 2) (+ m 1)))
   (else
    (collatz-iter (+ (* 3 n) 1) (+ m 1)))))

(define (euler14 n limit)
  (define (help-iter m len n limit)
    (let ((collatz (collatz-iter n 1)))
      (cond
       ((> n limit)
        (list m len))
       ((> collatz len)
        (help-iter n collatz (+ n 2) limit))
       (else
        (help-iter m len (+ n 2) limit)))))
  (help-iter 0 0 n limit))

collat​​z-iter

> (time (euler14 1 1000000))
cpu time: 1596 real time: 1596 gc time: 0

collat​​z-num

> (time (euler14 1 1000000))
cpu time: 1787 real time: 1789 gc time: 0

我的问题:

  1. 在方案中传递参数的成本有多大

  2. 在函数euler14中,我让限制作为帮助者的参数,这样可以节省一些时间吗?正如我在某处看到的那样,自由变量将有成本。

  3. 也许我太吝啬了。

1 个答案:

答案 0 :(得分:0)

再次。这是非常具体的实施!

我测试了你的代码,因为它确实消耗了内存并进行了大量的计算,我测试了这两个代码干扰第二个结果的顺序。我将每个文件中的两个测试分开并分别运行40次,并查看两者的平均运行时间。差异为num:1059.75,iter:1018.85。平均4%的差异,但在挑选两个样本时可能也是12%。我猜这个程序的运行时间平均可能超过4%,所以这两者之间的差异在一次运行中无关紧要。

您的代码中有一个额外的应用程序,以便检查参数对我进行此次测试的影响程度。在基本情况下使用参数是为了使Scheme不会优化它们:

(define (three-params x y z)
  (if (zero? x)
      (cons y z)
      (three-params (- x 1) x x)))

(define (two-params x y)
  (if (zero? x)
      (cons x y)
      (two-params (- x 1) x)))

(define (one-param x)
    (if (zero? x)
      (cons x x)
      (one-param (- x 1))))

(define numtimes 100000000)
(time (one-param  numtimes))
(time (two-params numtimes #f))
(time (three-params numtimes #f #f))

注释掉最后三行中的2行并制作3个文件。如果可以的话,编译它们。 几次运行的平均值。我选择了50,在Ikarus我得到以下平均值:

      agvms  diffms
one   402.4
two   417.82 15.42
three 433.14 15.32
two2  551.38 133.56 (with an extra addition compared to two)

只看50个结果,我看到时间在一,二,三之间重叠,但从统计上看,平均参数看起来是0,15ns。 ifzero?-cons以及gc的费用要高得多,即使它们是原始的。您不应该关注额外的申请和额外的论点。有时,不同的实现会以不同的方式优化您的代码,因此从racket更改为ikarus,gambit或chicken可能会改善您的代码。