测试的方法使用 timeit.Timer 对象,通过设置 setup 来定义一些准备工作代码,通过 stmt 设置需要测试运行时间的代码,通过 timeit 方法来测试性能(可以输入运行的次数,计算平均数)
实际测试时,首先需要进行热身,即先运行一次需要运行的内容,其次如果运行的时间少于1s则需要运行多次算平均。
https://zhuanlan.zhihu.com/p/104440866
# 设置需要测试的代码
timer = timeit.Timer(setup='import numpy as np',
stmt='np.zeros((4, 4))')
timer.timeit(10)
# 后续都会用到的测试代码
def bench_workload(workload):
"""Benchmark a workload
workload: a method that accept a num_repeat argument
and return its total execution time
"""
# 需要先预热一波
workload(1) # warmup
# 测试单次的运行时间
# 如果单词运行时间大于1s则则就运行一次
time = workload(1) # the time to run once
if time > 1: return time
# 如果单词运行时间少于1s,则运行多次计算平均
# The number of repeats to measure at least 1 second
num_repeats = max(int(1.0 / time), 5)
return workload(num_repeats) / num_repeats
print('time for np.zeros((4, 4)):', bench_workload(timer.timeit))
Function Call 的测试
在测试性能时,调用函数所花费的时间不可忽视
本节以 copyto 为例测试性能,展示了性能测试图。
下图横坐标是需要复制的向量长度,纵坐标是数据传输效率。
从图中可以看到,传输速度先是稳步上升然后达到饱和,饱和的原因带宽满了。
import timeit
import numpy as np
from matplotlib import pyplot as plt
from IPython import display
def np_setup(n):
return 'import numpy as np\n' \
'x = np.random.normal(size=%d).astype("float32")\n' \
'y = np.empty_like(x)\n'% n
def np_copy(n):
return timeit.Timer(setup=np_setup(n),
stmt='np.copyto(y, x)')
sizes = 2**np.arange(5, 20, 4).astype('int')
exe_times = [bench_workload(np_copy(n).timeit) for n in sizes]
# 图一
display.set_matplotlib_formats('svg')
# one float32 takes 4 bytes
plt.loglog(sizes, sizes*4/exe_times/1e9)
plt.xlabel('Vector length')
plt.ylabel('Throughput (GB/sec)')
plt.grid()
# 图二
plt.loglog(sizes, exe_times)
plt.xlabel('Vector length')
plt.ylabel('Time (sec)')
plt.grid()
python2
#coding=utf-8
import os
import sys
import codecs
import chardet
def convert(filename,out_enc="UTF-8"):
try:
content=codecs.open(filename,'r').read()
source_encoding=chardet.detect(content)['encoding']
#if source_encoding in ["UTF-8", "UTF-8-BOM"]:
#print filename + " " + source_encoding
print filename + " src_encodeing:" + source_encoding
content=content.decode(source_encoding).encode(out_enc)
codecs.open(filename,'w').write(content)
print filename + " convert_to_encodeing:" + out_enc
except IOError as err:
print("I/O error:{0}".format(err))
def explore(dir):
for root,dirs,files in os.walk(dir): # 查找所有文件
for file in files:
if os.path.splitext(file)[1] in ['.cpp','.c','.h','.hpp']: # 符合模式的 可以使用 glob.glob 简化
#print file
path=os.path.join(root,file)
convert(path)
def main():
explore(os.getcwd())
if __name__=="__main__":
main()
python3
#coding=utf-8
import os
import sys
import codecs
import chardet
def convert(filename,out_enc="utf-8"):
with open(filename, 'rb+') as f :
content = f.read()
encode = chardet.detect(content)['encoding']
if ( encode != out_enc):
try:
gbk_content = content.decode(encode)
uft_byte = bytes(gbk_content, encoding=out_enc)
f.seek(0)
f.write(uft_byte)
print(filename + "\n src_encodeing:" + encode + " convert_to_encodeing:" + out_enc)
except IOError as err:
print("convert " + filename + " failed")
def explore(dir):
for root,dirs,files in os.walk(dir):
for file in files:
if os.path.splitext(file)[1] in ['.cpp','.c']:
#print file
if file not in ["biz_ocr_charset.c", "biz_ocr_vdpr.c"]:
path=os.path.join(root,file)
convert(path)
def main():
change_dir=os.getcwd()+"/../code/"
explore(change_dir)
if __name__=="__main__":
main()
python glob.glob使用
import glob
list = glob.glob(‘*g’) # 查找文件全名 以 g 结尾的文件 jpg
print(list)
结果:
['dog.1012.jpg', 'dog.1013.jpg', 'dog.1014.jpg', 'dog.1015.jpg', 'dog.1016.jpg']
file_paths_LIST = glob.glob('%s/**/*%s' % (文件夹路径, 后缀名), recursive=True) #递归查找路径下 符合条件的文件
思路分析:
1.打印星星
2.使用嵌套循环打印星星
3.将星星替换成乘法口诀公式
使用嵌套循环打印星星
row = 1
while row < 10: # 行循环 1,2,...,9打印9行
# 这一行,需要操作n次 定义循环
# 列循环:操作的次数
col = 1
while col <= row: # 每行的数量 和当前行数相等
# 不需要换行
print('*',end='') # 默认会有换行,end='',不换行
col += 1 # 列数+1
# 换行
print()
row += 1 # 行数+1
将星星替换成乘法口诀
row = 1
while row < 10:# 行循环 1,2,...,9打印9行
# 这一行,需要操作n次 定义循环
# 列循环:操作的次数
col = 1
while col <= row:# 每行的数量 和当前行数相等
# 不需要换行
# 列*行=数据
print('%d * %d = %d'%(col,row,col*row),end='\t') # 默认会有换行,end='\t',打印制表符
col += 1 # 列数+1
# 换行
print()
row += 1 # 行数+1
倒序九九乘法表
分析:
只需要将行号从9开始即可
row = 9
while row > 0:# 行循环 9,8,...,1打印9行
# 这一行,需要操作n次 定义循环
# 列循环:操作的次数
col = 1
while col <= row: # 每行的数量 和当前行数相等
# 不需要换行
# 列*行=数据
print('%d * %d = %d'%(col,row,col*row),end='\t') # 默认会有换行
col += 1 # 列 + 1
# 换行
print()
row -= 1 # 行-1
def jmp(target_line):
target_frame = sys._getframe(3) #需要跳转
old_trance = target_frame.f_trace
#target_frame.f_trace_opcode = True
def new_trace_hook(cur_frame, event, arg):
if event == 'line' and cur_frame == target_frame:
try:
cur_frame.f_lineno = target_line
except ValueError as e:
print("jmp failed: " + str(e))
frame.f_trace = old_trance
return old_trance
return old_trance
frame.f_trace = new_trace_hook
sys.settrace(new_trace_hook)
class updateFunc(ast.NodeTransformer):
def __init__(self):
pass
def visit_BinOp(self, node):
node.op = ast.Mult()
return node
class warpFunc():
def __init__(self, func):
self.func = func
self.new_func = {}
def __call__(self, *args, **kwargs):
ast_code, src_code = get_code_ast(self.func) # ast.parse inspect.getsourcecode
ast_code.body[0].decorator_list = []
trs = updateFunc()
newast = trs.visit(ast_code)
global_vars = {**globals(), **locals()}
local_vars = {}
exec(compile(newast, "file_temp.py", mode='exec'), global_vars, local_vars)
return local_vars[self.func.__name__](*args)
def trans(func):
def _deco(func, *args, **kwargs):
new_func = warpFunc(func)
return new_func(*args)
@trans
def add(a, b)
c = a + b
return c
print(add(3, 5))