2017-08-23 13 views
0

私はフィボナッチ関数を使ってmemoizedデコレータ運動をしています。 memoized関数は、結果が再び計算される代わりに辞書から結果を返すので、入力が大きくなるとはるかに高速になるはずです。メモ化デコレータが元の関数よりも遅く実行される

私はを使用して、voをオフにしてメモした関数の実行時間を測定しています。 私が得た結果は、私が期待しているものとまったく逆です。デコレータのない実行ははるかに速く実行されます。

# memorized decorator for fibonacci series 
def mem_fib(f): 
    def wrapper(n): 
     wrapper.d = {} # create the attr member of THIS wrapper 
     if n in wrapper.d: 
      return wrapper.d[n] 
     wrapper.d[n] = f(n) # save f() return in a dict 
     return wrapper.d[n] 
    return wrapper 

@mem_fib 
def fibonacci(n): 
    assert n >= 0 
    if n < 2: 
     return n 
    return fibonacci(n-1) + fibonacci(n-2) 

私はPyCharmのPythonのコンソールでコマンドを実行しています。

@withデコレータ

>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators')) 
19.6940833939 
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
85.7157191166 

デコレータ

>>> print(timeit.timeit('decorators.fibonacci(7)', setup='import decorators')) 
5.10131571594 
>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
21.9784012801 

のない私ははtimeit複数回走った、私はちょうどそれを合計する1つの出力を置きます。私は何が欠けていますか?

おかげ

更新:ダニエルの答えのおかげで、私は私のミスを発見しました。私はラッパーの外で辞書の作成を移動し、結果ははるかに優れていた。

>>> print(timeit.timeit('decorators.fibonacci(10)', setup='import decorators')) 
0.248986574759 
+0

大きな値には疲れましたか?私の推測では、7と10の場合、メモ作成によって導入されたわずかなオーバーヘッドは実際の計算のコストよりも大きいことになります。私はfibbonacci(100)の場合、期待される結果が得られると思います。 –

+1

それはあなたの主張の声明のためでしょうか?また、補足として、最後にパスステートメントは必要ありません。負のnをチェックしてエラーを出し、ベースケースをチェックして戻ります。両方のチェックが失敗した場合は、再帰的なケースでなければならないため、elseを使用する必要はありません。 – Mai

+0

この小さな変更は、コードを読みやすくします。注釈のおかげです。 – Vinny

答えて

5

あなたwrapper関数は常にwrapper.d = {}を行いますので、あなたは、新しい辞書に関数が呼び出されるたびに作成します。したがって、キャッシュにはデータが格納されず、毎回辞書を作成するためのオーバーヘッドが発生します。

mem_fibから返される前に、その行がその関数の外に移動する必要があります。

+0

どのように私はそれを逃したのか分かりません!ありがとう! (mem_fibの中で)辞書の作成を(mem_fibの中で)動かすと、結果は私が期待した通りだった – Vinny

+0

'print(timeit.timeit( 'decorators.fibonacci(10)'、setup = 'import decorators')) 0.248986574759' – Vinny

関連する問題