【问题标题】:Different memoization techniques in RubyRuby 中不同的记忆技术
【发布时间】:2011-02-27 00:13:44
【问题描述】:

如果您是 ruby​​ 程序员,那么您可能会遇到哈希块记忆模式。举一个简单的例子,我向您展示斐波那契数列的记忆版本:

fib_hash = Hash.new do |h,i|
  h[i] = h[i-1] + h[i-2]
end
# establish the base cases
fib_hash[1] = 1; fib_hash[2] = 1

当然,这不是创建斐波那契数列的记忆版本的唯一方法。您还可以执行以下操作:

@cache = {}; @cache[1] = 1; @cache[2] = 1
def memo_fib(n)
  @cache[n] ||= (memo_fib(n-1) + memo_fib(n-2))
end

希望您看到哈希块记忆模式如何映射到在许多其他语言中更为常见的第二个版本。我想知道的是这两个版本之间是否有任何区别?我无法摆脱散列块版本更有效的感觉,但我无法证明为什么。

【问题讨论】:

    标签: ruby performance memoization


    【解决方案1】:

    MRI 1.8.7 的基准测试结果:

    • 哈希块:0.44 秒
    • 非散列块:0.41 秒

    在 MRI 1.9.0 中:

    • 哈希块:0.24 秒
    • 非散列块:0.28 秒

    基准是计算从 1 到 1000 的斐波那契数的 100 次迭代,在每次迭代开始时重置哈希或缓存。

    这是哈希块的基准:

    def reset_fib_hash                                                              
      @fib_hash = Hash.new do |h,i|
        h[i] = h[i-1] + h[i-2]
      end
      # establish the base cases                                                    
      @fib_hash[1] = 1; @fib_hash[2] = 1
    end
    
    start_time = Time.now
    100.times do
      reset_fib_hash
      (1..1000).each do |i|
        @fib_hash[i]
      end
    end
    p Time.now - start_time
    

    这是非散列块的基准:

    def reset_fib_hash
      @cache = {}; @cache[1] = 1; @cache[2] = 1
    end
    
    def memo_fib(n)
      @cache[n] ||= (memo_fib(n-1) + memo_fib(n-2))
    end
    
    start_time = Time.now
    100.times do
      reset_fib_hash
      (1..1000).each do |i|
        memo_fib(i)
      end
    end
    p Time.now - start_time
    

    【讨论】:

    • 所以方法调用比块调用便宜。很高兴知道,谢谢。
    • 其实我在1.9.1的ruby版本上做了测试,hash block版本更快。
    • @davidk01,我很惭愧没有说我测试了哪个版本。正如您可能猜到的那样,它是 1.8.7。我已将 MRI 1.9.0 结果添加到答案中。
    猜你喜欢
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多