简体   繁体   English

提高我的代码速度

[英]Increase the speed of my code

i have created the code below, it takes a series of values, and generates 10 numbers between x and r with an average value of 8000 我创建了下面的代码,它使用一系列值,并在x和r之间生成10个均值为8000的数字

in order to meet the specification to cover the range as well as possible, I also calculated the standard deviation, which is a good measure of spread. 为了尽可能满足覆盖范围的规范,我还计算了标准差,这是扩展的好方法。 So whenever a sample set meets the criteria of mean of 8000, I compared it to previous matches and constantly choose the samples that have the highest std dev (mean always = 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]

i take the first value in the list and use this as a timing value, however this code is REALLY slow, i need to call this piece of code several thousand times during the simulation so need to improve the efficency of the code some how 我将列表中的第一个值用作时序值,但是此代码确实很慢,我需要在仿真过程中多次调用此代码数千次,因此需要提高代码效率

anyone got any suggestions on how to ? 任何人有任何建议如何?

To see where we'd get the best speed improvements, I started by profiling your code. 为了了解我们将在哪些方面获得最快的速度改进,我首先分析了您的代码。

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

The top of the results show where your code is spending most of its 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__)
...

From this output, we can see that we're spending ~7.5 seconds (out of 10.6 seconds) generating random numbers. 从此输出中,我们可以看到我们花费了大约7.5秒(从10.6秒中)生成随机数。 Therefore, the only way to make this noticeably faster is to generate fewer random numbers or generate them faster. 因此,使此速度明显更快的唯一方法是生成更少的随机数或更快地生成它们。 You're not using a cryptographic random number generator so I don't have a way to make generating numbers faster. 您没有使用密码随机数生成器,所以我没有办法更快地生成数字。 However, we can fudge the algorithm a bit and drastically reduce the number of values we need to generate. 但是,我们可以对算法稍加改动,并大大减少我们需要生成的值的数量。

Instead of only accepting samples with a mean of exactly 8000, what if we accepted samples with a mean of 8000 +- 0.1% (then we're taking samples with a mean of 7992 to 8008)? 如果不接受均值恰好为8000的样本,那么如果我们接受均值为8000±0.1%的样本(那我们将取均值为7992至8008的样本)怎么办? By being a tiny bit inexact, we can drastically speed up the algorithm. 由于有点不精确,我们可以大大加快算法的速度。 I replaced the while condition with: 我将while条件替换为:

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

Where epsilon = target_sum * 0.001 . 其中epsilon = target_sum * 0.001 Then I ran the script again and got much better profiler numbers. 然后,我再次运行了脚本,并获得了更好的探查器编号。

         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)

Allowing the mean to be up to 0.1% off of the target dropped the number of calls to randint by 100x. 允许平均值比目标高出0.1%, randint的调用randint减少100倍。 Naturally, the code also runs 100x faster (and now spends most of its time printing to console). 自然,代码的运行速度也快了100倍(现在花了大部分时间在控制台上打印)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM