3

これはコードの最初の最適化であり、興奮しています。いくつかの記事を読みましたが、まだいくつか質問があります。

1) まず、以下のコードで時間がかかるのは何ですか? ここは配列だと思います:array.append(len(set(line.split())))。私はPythonのリストがより速く動作することをオンラインで読みましたが、ここではリストを使用していません。これを改善する方法を知っている人はいますか?

2) 他に欠けている改善点はありますか?

3)また、オンラインでは、 for ループがコードを大幅に遅くすると言われています。ここは改善できますか?(Cでコードを書くのが最善だと思いますが、:D)

4) 人々が常に「ncalls」と「tottime」を見ることを提案するのはなぜですか? 私にとっては、「percall」の方が理にかなっています。関数または呼び出しの速度を示します。

5) こちらの正解クラス B で、彼はリストを適用しました。彼は?私にとっては、物事を遅くすると思われる配列とFORループがまだ見られます。 numpy数値配列を成長させる最速の方法

ありがとうございました。

新しい cProfile 結果:

 618384 function calls in 9.966 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    19686    3.927    0.000    4.897    0.000 <ipython-input-120-d8351bb3dd17>:14(f)
    78744    3.797    0.000    3.797    0.000 {numpy.core.multiarray.array}
    19686    0.948    0.000    0.948    0.000 {range}
    19686    0.252    0.000    0.252    0.000 {method 'partition' of 'numpy.ndarray' objects}
    19686    0.134    0.000    0.930    0.000 function_base.py:2896(_median)
        1    0.126    0.126    9.965    9.965 <ipython-input-120-d8351bb3dd17>:22(<module>)
    19686    0.125    0.000    0.351    0.000 _methods.py:53(_mean)
    19686    0.120    0.000    0.120    0.000 {method 'reduce' of 'numpy.ufunc' objects}
    19686    0.094    0.000    4.793    0.000 function_base.py:2747(_ureduce)
    19686    0.071    0.000    0.071    0.000 {method 'flatten' of 'numpy.ndarray' objects}
    19686    0.065    0.000    0.065    0.000 {method 'format' of 'str' objects}
    78744    0.055    0.000    3.852    0.000 numeric.py:464(asanyarray)

新しいコード:

import numpy
import cProfile

pr = cProfile.Profile()
pr.enable()

#paths to files
read_path = '../tweet_input/tweets.txt'
write_path = "../tweet_output/ft2.txt"


def f(a):  
    for i in range(0, len(array)):
        if a <= array[i]:
            array.insert(i, a)
            break
    if 0 == len(array):
        array.append(a)

try:
    with open(read_path) as inf, open(write_path, 'a') as outf:
        array = []
        #for every line (tweet) in the file
        for line in inf:                                            ###Loop is bad. Builtin function is good
            #append amount of unique words to the array
            wordCount = len(set(line.split()))
            #print wordCount, array
            f(wordCount)
            #write current median of the array to the file
            result = "{:.2f}\n".format(numpy.median(array))
            outf.write(result)
except IOError as e:
    print 'Operation failed: %s' % e.strerror


###Service
pr.disable()
pr.print_stats(sort = 'time')

古い cProfile 結果: 13.195 秒で 551211 関数呼び出し 順序付け: 内部時間
ncalls tottime percall cumtime percall filename:lineno(function) 78744 10.193 0.000 10.193 0.000 {numpy.core.multiarray.array}

古いコード:

    with open(read_path) as inf, open(write_path, 'a') as outf:
        array = []
        #for every line in the file
        for line in inf:                            
            #append amount of unique words to the array
            array.append(len(set(line.split())))
            #write current median of the array to the file
            result = "{:.2f}\n".format(numpy.median(array))
            outf.write(result)
4

1 に答える 1

1

Numpy は、O(n log n) である中央値検索アルゴリズムを使用します。1 行に 1 回呼び出すnumpy.meadianため、アルゴリズムは最終的に O(n^2 log n) になります。

これを改善するにはいくつかの方法があります。1 つは、配列をソートしたままにすることです (つまり、ソートされた順序を維持する位置に各要素を挿入します)。各挿入は O(n) かかり (配列への挿入は線形時間操作です)、ソートされた配列の中央値の取得は O(1) であるため、これは最終的に O(n^2) になります。

プロファイリングの場合、主に見たいのは ですtottime。これにより、プログラムが関数で費やした合計時間がわかるからです。あなたの例のように、遅い関数 ( high ) が数回しか呼び出されない ( low ) 場合、他の関数と比較して重要で percallなくなることがあるため、あまり役に立たないことがあります。percallnumcallstottime

于 2015-07-11T19:47:37.593 に答える