Scheme 方案-带“备注”的备忘录;强迫;及;延迟“;速度比较

Scheme 方案-带“备注”的备忘录;强迫;及;延迟“;速度比较,scheme,lazy-evaluation,fibonacci,memoization,Scheme,Lazy Evaluation,Fibonacci,Memoization,考虑到上面的两个斐波那契函数,我预计第二个会运行得更快,因为scheme将记忆应用于强制延迟对象 然而,第二个fiboN运行较慢。为什么会这样?我对Scheme中的自动回忆录的看法是否错误?你把回忆录与延迟(又称懒惰)评估混淆了——看看这一点,了解这两个概念之间的区别 当然,fiboN的第二个实现被延迟了,但它没有记忆任何东西-当然,一旦我们force一个值,它就不必再次被强制执行,但这并没有改变一个事实,即这是一个递归函数,对于我们已经获得的值,它会被反复调用,延迟/强制每个值的额外成本将使其

考虑到上面的两个斐波那契函数,我预计第二个会运行得更快,因为scheme将记忆应用于强制延迟对象


然而,第二个fiboN运行较慢。为什么会这样?我对Scheme中的自动回忆录的看法是否错误?

你把回忆录与延迟(又称懒惰)评估混淆了——看看这一点,了解这两个概念之间的区别

当然,
fiboN
的第二个实现被延迟了,但它没有记忆任何东西-当然,一旦我们
force
一个值,它就不必再次被强制执行,但这并没有改变一个事实,即这是一个递归函数,对于我们已经获得的值,它会被反复调用,延迟/强制每个值的额外成本将使其比第一次实现慢

这里有一个可能的实现,它真正使用了记忆,诀窍是将已经计算的值保存在我们可以有效访问它们的地方-本例中的哈希表:

(define fibo   ; fibonacci
  (lambda (n)
    (cond ((= n 0) 0)
          ((= n 1) 1)
          ((= n 2) 1)
          (else (+ (fibo (- n 1)) (fibo(- n 2))
     )))))

(time (fibo 20))

(define (fiboN n)   ; fibonacci
    (delay (cond ((= n 0) 0)
          ((= n 1) 1)
          ((= n 2) 1)
          (else (+ (force (fiboN (- n 1))) (force (fiboN(- n 2))))))))

(time force( force (fiboN 20)))
结果表明,这要快得多:

(define fiboN
  (let ((memo (make-hash '((0 . 0) (1 . 1)))))
    (lambda (n)
      (unless (hash-has-key? memo n)
        (hash-set! memo n (+ (fiboN (- n 1)) (fiboN (- n 2)))))
      (hash-ref memo n))))

你混淆了记忆和延迟(又称懒惰)评估——看看这两个概念之间的区别

当然,
fiboN
的第二个实现被延迟了,但它没有记忆任何东西-当然,一旦我们
force
一个值,它就不必再次被强制执行,但这并没有改变一个事实,即这是一个递归函数,对于我们已经获得的值,它会被反复调用,延迟/强制每个值的额外成本将使其比第一次实现慢

这里有一个可能的实现,它真正使用了记忆,诀窍是将已经计算的值保存在我们可以有效访问它们的地方-本例中的哈希表:

(define fibo   ; fibonacci
  (lambda (n)
    (cond ((= n 0) 0)
          ((= n 1) 1)
          ((= n 2) 1)
          (else (+ (fibo (- n 1)) (fibo(- n 2))
     )))))

(time (fibo 20))

(define (fiboN n)   ; fibonacci
    (delay (cond ((= n 0) 0)
          ((= n 1) 1)
          ((= n 2) 1)
          (else (+ (force (fiboN (- n 1))) (force (fiboN(- n 2))))))))

(time force( force (fiboN 20)))
结果表明,这要快得多:

(define fiboN
  (let ((memo (make-hash '((0 . 0) (1 . 1)))))
    (lambda (n)
      (unless (hash-has-key? memo n)
        (hash-set! memo n (+ (fiboN (- n 1)) (fiboN (- n 2)))))
      (hash-ref memo n))))

非常感谢你。我理解你版本中的值是如何被记忆的。但是,fibo的第一个版本中的值是否与第二个版本中的值一样存储?如果不是,那么这是真的吗?那么延迟和强制在速度方面的成本超过了保存任何存储值的成本?非常感谢。我理解你版本中的值是如何被记忆的。但是,fibo的第一个版本中的值是否与第二个版本中的值一样存储?如果不是,那么就速度而言,延迟和强制的成本是否比保存任何存储值都要高?