如何在Python中精准测量高频重复的简单操作耗时?
问题描述
在Python中处理大型数据集时,需要反复执行几个简短操作。随着数据集增大,整个流程运行时间呈二次增长,计划先定位耗时最长的操作再优化,但测量操作耗时出现不一致:各操作耗时总和与总运行时间差距很大。
示例代码如下:
import time import tqdm all_times = {"Mult":0,"Add":0,"Full":0} s1 = time.process_time() for i in tqdm.tqdm(range(int(1e4))): for j in range(i): s = time.process_time() z = i*i all_times["Mult"] += (time.process_time() - s) s = time.process_time() z = i+i all_times["Add"] += (time.process_time() - s) all_times["Full"] += (time.process_time() - s1) print(all_times)
运行结果类似:{'Mult': 17.977712000036018, 'Add': 17.74207199997629, 'Full': 69.089015},实际时钟测量总耗时约70秒。移除内部计时操作后整体运行时间几乎无变化,迭代递增不可能耗时如此多,询问如何精准测量这类短操作的耗时。
解决方案
- 批量计时替代单次计时:短操作的单次耗时远小于计时函数本身的开销,单独计时会放大误差。可以把相同操作批量执行N次,再计算单次平均耗时,大幅降低计时操作带来的误差。
示例代码:
import time import tqdm all_times = {"Mult":0,"Add":0,"Full":0} batch_size = 1000 # 批量执行次数 s1 = time.process_time() for i in tqdm.tqdm(range(int(1e4))): # 按批量数调整循环次数 for j in range(i // batch_size): # 批量测量乘法 s = time.process_time() for _ in range(batch_size): z = i*i all_times["Mult"] += (time.process_time() - s) / batch_size # 批量测量加法 s = time.process_time() for _ in range(batch_size): z = i+i all_times["Add"] += (time.process_time() - s) / batch_size all_times["Full"] += (time.process_time() - s1) print(all_times)
- 使用
timeit模块:Python内置的timeit专门用于测量小段代码的执行时间,它会自动重复执行代码多次来减少误差,还会自动排除计时操作本身的开销。
示例代码:
import timeit # 模拟循环中的i值,可替换为数据集实际值 mult_avg = timeit.timeit(lambda i=5: i*i, number=1000000) / 1000000 add_avg = timeit.timeit(lambda i=5: i+i, number=1000000) / 1000000 print(f"单次乘法平均耗时:{mult_avg}秒") print(f"单次加法平均耗时:{add_avg}秒")
减少循环内的额外操作:原代码中每次循环都要执行两次
time.process_time()和字典赋值,这些操作的累积开销会被算进总时间,但未被统计到目标操作耗时里。可以把多次操作的计时合并,或把计时逻辑移到循环外,只统计核心操作的批量耗时。使用
cProfile做全面性能分析:如果需要定位整个程序的性能瓶颈,cProfile能生成详细的性能报告,直接展示各代码段的耗时占比。
示例代码:
import cProfile def process_data(): all_times = {"Mult":0,"Add":0} for i in range(int(1e4)): for j in range(i): z = i*i z = i+i cProfile.run('process_data()', sort='cumulative')
运行后会输出各代码段的调用次数、总耗时、单次耗时等信息,直观定位耗时最多的部分。
内容的提问来源于stack exchange,提问作者Laura
相关产品推荐
相关产品推荐

