2017-04-25 10 views
0

速度を上げるには、一連の値をとり とカバーに仕様を満たすために8000iは以下のコードを作成して自分のコード

の平均値XとRとの間の10個の数字を生成します可能な限り範囲を広げ、標準偏差も計算しました。これは広がりの良い尺度です。サンプルセットは、8000の平均値の基準を満たしている時はいつでもだから、私は前の試合にそれを比較し、常に最高のSTD DEVを持っているサンプルを選択

def node_timing(average_block_response_computational_time, min_block_response_computational_time, max_block_response_computational_time): 
    sample_count = 10 
    num_of_trials = 1 

    # print average_block_response_computational_time 
    # print min_block_response_computational_time 
    # print max_block_response_computational_time 

    target_sum = sample_count * average_block_response_computational_time 
    samples_list = [] 
    curr_stdev_max = 0 
    for trials in range(num_of_trials): 
     samples = [0] * sample_count 
     while sum(samples) != target_sum: 
      samples = [rd.randint(min_block_response_computational_time, max_block_response_computational_time) for trial in range(sample_count)] 
     # print ("Mean: ", st.mean(samples), "Std Dev: ", st.stdev(samples),) 
     # print (samples, "\n") 
     if st.stdev(samples) > curr_stdev_max: 
      curr_stdev_max = st.stdev(samples) 
      samples_best = samples[:] 
     return samples_best[0] 

私は最初の値をとる(常に= 8000の意味)このコードは非常に遅いです、私はシミュレーション中にこのコードを数千回呼び出す必要がありますので、コードの効率を改善する必要があります。

誰にでも何か提案がありますの仕方 ?

+0

アップグレードの可能性はありますが、forのサンプルを開始する必要はありません。また、samples_bestを設定するときにリストをコピーする必要はありません。たくさん改善したい場合は、pypyやcythonを使うことができます。最後に、それは私には非確定的だと思われますが...決定論的なアルゴリズムを書くことはできませんか?たぶん平均とすべての要素を開始し、ランダムに変更しますか? –

+0

小さい:私はこれがうまくいくのに驚いています: 'の間にsum(samples)!= target_sum:'、 'samples'はランダムな整数を含んでいます。確かに '> = '比較のようなものが良いでしょうか? – Evert

+0

私の意見では、Pythonの 'random'モジュールは遅く、ほとんどのコードをnumpyまたはnumbaに移動します。 –

答えて

1

私たちはどこでスピードを改善するのかを知るために、コードのプロファイリングを始めました。この出力から

23561178 function calls (23561176 primitive calls) in 10.612 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
    4502300 3.694 0.000 7.258 0.000 random.py:172(randrange) 
    4502300 2.579 0.000 3.563 0.000 random.py:222(_randbelow) 
    4502300 1.533 0.000 8.791 0.000 random.py:216(randint) 
    450230 1.175 0.000 9.966 0.000 counter.py:19(<listcomp>) 
    4608421 0.690 0.000 0.690 0.000 {method 'getrandbits' of '_random.Random' objects} 
     100 0.453 0.005 10.596 0.106 counter.py:5(node_timing) 
    4502300 0.294 0.000 0.294 0.000 {method 'bit_length' of 'int' objects} 
    450930 0.141 0.000 0.150 0.000 {built-in method builtins.sum} 
     100 0.016 0.000 0.016 0.000 {built-in method builtins.print} 
     600 0.007 0.000 0.025 0.000 statistics.py:105(_sum) 
    2200 0.005 0.000 0.006 0.000 fractions.py:84(__new__) 
... 

、我々は10.6秒のうち4.2(〜7.5秒を費やしていることがわかります。

import cProfile 
pr = cProfile.Profile() 
pr.enable() 
for i in range(100): 
    print(node_timing(8000, 7000, 9000)) 
pr.disable() 
pr.print_stats(sort='time') 

結果の上部には、あなたのコードは、そのほとんどの時間を費やしている場所を示し)乱数を生成する。したがって、これを顕著に速くする唯一の方法は、より少ない数の乱数を生成するか、より速く生成することです。暗号乱数ジェネレータを使用していないので、数字を速く生成する方法はありません。しかし、私たちは少しアルゴリズムを微調整し、生成する必要がある値の数を大幅に減らすことができます。

平均が8000のサンプルのみを受け入れるのではなく、平均値が8000±0.1%のサンプルを受け入れると(平均して7992〜8008のサンプルを取っています)不正確な小さなビットであることによって、我々はアルゴリズムを大幅に高速化することができます。

while abs(sum(samples) - target_sum) > epsilon 

epsilon = target_sum * 0.001:私はwhile条件を置き換えます。その後、スクリプトをもう一度実行して、プロファイラ番号をはるかに上げました。平均が目標のオフ最大0.1%されることを可能にする

  232439 function calls (232437 primitive calls) in 0.163 seconds 

    Ordered by: internal time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     100 0.032 0.000 0.032 0.000 {built-in method builtins.print} 
    31550 0.026 0.000 0.053 0.000 random.py:172(randrange) 
    31550 0.019 0.000 0.027 0.000 random.py:222(_randbelow) 
    31550 0.011 0.000 0.064 0.000 random.py:216(randint) 
    4696 0.010 0.000 0.013 0.000 fractions.py:84(__new__) 
    3155 0.008 0.000 0.073 0.000 counter.py:19(<listcomp>) 
     600 0.008 0.000 0.039 0.000 statistics.py:105(_sum) 
     100 0.006 0.000 0.131 0.001 counter.py:4(node_timing) 
    32293 0.005 0.000 0.005 0.000 {method 'getrandbits' of '_random.Random' objects} 
    1848 0.004 0.000 0.009 0.000 fractions.py:401(_add) 

は100Xによってrandintにコールの数を落としました。もちろん、このコードも100倍速く実行されます(そして、今ではほとんどの時間をコンソールに費やしています)。

関連する問題