我创建了下面的代码,它需要一系列值, 并在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]
我取列表中的第一个值并将其用作定时值,但是这个代码真的很慢,我需要在模拟过程中调用这段代码几千次,所以需要提高代码的效率一些如何
有人对如何获得任何建议?
答案 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倍(现在大部分时间都打印到控制台)。