2017-04-25 114 views
0

我已經建立下面的代碼速度,它需要一系列值, 並用8000增加的我的代碼

的平均值,以滿足規範,以覆蓋生成X和R 10級之間的數字範圍以及可能的情況下,我也計算了標準偏差,這是一個很好的衡量指標。因此,只要樣本集滿足8000均值的標準,我把它比以前的比賽和不斷選擇具有最高標準偏差的樣本(平均總= 8000)

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] 

我採取的第一個值中列表並將其用作定時值,但是此代碼非常慢,我需要在模擬過程中將這段代碼調用數千次,因此需要提高代碼的效率。有些人如何獲得任何建議如何 ?

+0

可能小的升級,但你不需要在for中啓動示例。在設置samples_best時,您也不需要複製列表。如果你想改進很多,你可以嘗試使用pypy或cython。最後,雖然對我來說似乎是不確定的......你不能爲它寫一個確定性的算法嗎?也許開始所有的元素與平均值,然後隨機改變它們? –

+0

小撇:我很驚訝這會起作用:'while sum(samples)!= target_sum:',因爲'samples'包含隨機整數。肯定像'> ='比較比較好? – Evert

+0

在我看來,python的'random'模塊很慢,我會將大部分代碼移入numpy或numba。 –

回答

1

要查看我們能夠獲得最佳速度改進的地方,我首先分析您的代碼。

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') 

結果的頂部顯示在您的代碼花費其大部分時間:

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__) 
... 

從這個輸出,我們可以看到,我們花〜7.5秒(出10.6秒)生成隨機數字。因此,使其顯着更快的唯一方法是生成更少的隨機數或更快地生成它們。你沒有使用加密隨機數生成器,所以我沒有辦法讓生成的數字更快。但是,我們可以對算法進行一些修改,並大幅減少我們需要生成的值的數量。

而不是隻接受平均值爲8000的樣本,如果我們接受平均值爲8000±0.1%的樣本(那麼我們的樣本平均值爲7992至8008)會怎樣?通過稍微不精確,我們可以大大加快算法的速度。我更換了while條件有:

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

哪裏epsilon = target_sum * 0.001。然後我再次運行腳本,並獲得了更好的分析器編號。

  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) 

使平均將增長0.1%,離目標由100×掉線的次數randint。當然,代碼的運行速度也快了100倍(現在大部分時間都是打印到控制檯上)。