2012-01-28 10 views
7

高次関数を使用しています& Lambdasは実行時間を&にするとメモリの効率は良くなるか悪くなりますか? 例えば、リスト内のすべての数値を乗算する:高次関数vsループ - 実行時間とメモリ効率?

nums = [1,2,3,4,5] 
prod = 1 
for n in nums: 
    prod*=n 

VS

prod2 = reduce(lambda x,y:x*y , nums) 

はHOFバージョンは、それがコードの少ない行をだ以外ループバージョン上の任意の利点を持っている/機能的アプローチを使用?

EDIT:

私は私が必要との評判を持っていないような答えとしてこれを追加することはできませんよ。私は@DSM

def test1():   
    s= """ 
    nums = [a for a in range(1,1001)] 
    prod = 1 
    for n in nums: 
     prod*=n 
    """    
    t = timeit.Timer(stmt=s) 
    return t.repeat(repeat=10,number=100)  

def test2(): 
    s=""" 
    nums = [a for a in range(1,1001)]  
    prod2 = reduce(lambda x,y:x*y , nums) 
    """ 
    t = timeit.Timer(stmt=s) 
    return t.repeat(repeat=10,number=100) 

によって示唆されているようにはtimeitを使用してループ& HOFのアプローチをプロファイリングするために結ばれ、これが私の結果である :

Loop: 
[0.08340786340144211, 0.07211491653462579, 0.07162720686361926, 0.06593182661083438, 0.06399049758613146, 0.06605228229559557, 0.06419744588664211, 0.0671893658461038, 0.06477527090075941, 0.06418023793167627] 
test1 average: 0.0644778902685 
HOF: 
[0.0759414223099324, 0.07616920129277016, 0.07570730355421262, 0.07604965128984942, 0.07547092059389193, 0.07544737286604364, 0.075532959799953, 0.0755039779810629, 0.07567424616704144, 0.07542563650187661] 
test2 average: 0.0754917512762 

平均ループアプローチではHOFsを使用するよりも速くなるようです。

+2

あなたははtimeitモジュールに精通していますか?自分でパフォーマンスをテストできます。 – DSM

+0

いいえ、私はそれに精通していません。私はtimeitのためにgoogleします。私はそれがプロファイリングツールだと思います。しかし、理論的な見地からHOFの利点を知りたいと思っています。 – Bharat

+0

@RBK問題は、理論上のパースペクティブがあなたの質問(ランニングタイムとメモリ効率)に答えないことです。 – Icarus

答えて

0

私の経験から得たループは非常に速くネストされていて、深いネストではなく、複雑な高次数演算、単純な演算、ループの単一レイヤーで他の方法より速く、ループまたはループのインデックスとして整数だけが使用されている限り、実際にあなたがやっていることにも依存します

また、高次関数が同じくらい多くのループを生成する可能性があります。 ループプログラムのバージョンは少し遅いかもしれませんが、両方を実行する必要があります。

7

高次関数は非常に高速になる可能性があります。例えば

map(ord, somebigstring)は、同等のリスト内包[ord(c) for c in somebigstring]よりはるかに高速です。

  • マップ()somebigstringの長さに結果文字列をプリサイズ:3つの理由元勝。対照的に、リストの理解は、realloc()に多くの呼び出しを行う必要があります。

  • map()はordの最初の参照を行うだけで、最初にグローバルをチェックしてから、それをチェックして組み込みで見つけます。リストの理解は、すべての反復でこの作業を繰り返さなければなりません。

  • マップの内側ループはCスピードで実行されます。リストの理解のためのループ本体は一連の純粋なPythonのステップであり、それぞれがeval-loopによってディスパッチまたは処理される必要があります。ここで

いくつかのタイミングの予測を確認しています

>>> from timeit import Timer 
>>> print min(Timer('map(ord, s)', 's="x"*10000').repeat(7, 1000)) 
0.808364152908 
>>> print min(Timer('[ord(c) for c in s]', 's="x"*10000').repeat(7, 1000)) 
1.2946639061 
+0

ああ、私はその地図()が他の方法よりも効率的に多くのことをしているのを見ています。スピードは私たちが達成しようとしているものによって決まると思います。 HOFが最速ではないことを示唆していると思われる[Pythonでリストのリストからフラットリストを作る](http://stackoverflow.com/q/952914/78845)の議論は、 – Bharat

+0

HOFの使用はその議論に付随しています。そこでのタイミングは、関数呼び出しオーバーヘッドなどの他の要因によって支配されています。 –

+0

はい、地図が速いようです。私はあなたのプロファイリングコードを試して、同じ結果を得ました。私は自分自身を説得するためにいくつかのプロファイリングをするつもりです:) – Bharat

関連する問題