提高我的代码速度

时间:2017-04-25 21:58:29

标签: python

我创建了下面的代码,它需要一系列值, 并在x和r之间生成10个数字,平均值为8000

为了满足规范以尽可能地覆盖范围,我还计算了标准偏差,这是一个很好的传播衡量标准。因此,每当样本集符合平均值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]

我取列表中的第一个值并将其用作定时值,但是这个代码真的很慢,我需要在模拟过程中调用这段代码几千次,所以需要提高代码的效率一些如何

有人对如何获得任何建议?

1 个答案:

答案 0 :(得分: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±0.1%的样本(那么我们的样本平均值为7992到8008),而不仅仅接受平均值为8000的样本呢?通过一点点不精确,我们可以大大加快算法速度。我将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倍(现在大部分时间都打印到控制台)。