forked from bys0318/QTO
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_TimeCounter.py
122 lines (97 loc) · 4.19 KB
/
_TimeCounter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import time
import warnings
from contextlib import contextmanager
import torch
class TimeCounter:
names = dict()
# Avoid instantiating every time
@classmethod
def count_time(cls, log_interval=1, warmup_interval=1, with_sync=True):
assert warmup_interval >= 1
def _register(func):
if func.__name__ in cls.names:
raise RuntimeError(
'The registered function name cannot be repeated!')
# When adding on multiple functions, we need to ensure that the
# data does not interfere with each other
cls.names[func.__name__] = dict(
count=0,
pure_inf_time=0,
log_interval=log_interval,
warmup_interval=warmup_interval,
with_sync=with_sync)
def fun(*args, **kwargs):
count = cls.names[func.__name__]['count']
pure_inf_time = cls.names[func.__name__]['pure_inf_time']
log_interval = cls.names[func.__name__]['log_interval']
warmup_interval = cls.names[func.__name__]['warmup_interval']
with_sync = cls.names[func.__name__]['with_sync']
count += 1
cls.names[func.__name__]['count'] = count
if with_sync and torch.cuda.is_available():
torch.cuda.synchronize()
start_time = time.perf_counter()
result = func(*args, **kwargs)
if with_sync and torch.cuda.is_available():
torch.cuda.synchronize()
elapsed = time.perf_counter() - start_time
if count >= warmup_interval:
pure_inf_time += elapsed
cls.names[func.__name__]['pure_inf_time'] = pure_inf_time
if count % log_interval == 0:
times_per_count = 1000 * pure_inf_time / (
count - warmup_interval + 1)
print(
f'[{func.__name__}]-{count} times per count: '
f'{times_per_count:.1f} ms',
flush=True)
return result
return fun
return _register
@classmethod
@contextmanager
def profile_time(cls,
func_name,
log_interval=1,
warmup_interval=1,
with_sync=True):
assert warmup_interval >= 1
warnings.warn('func_name must be globally unique if you call '
'profile_time multiple times')
if func_name in cls.names:
count = cls.names[func_name]['count']
pure_inf_time = cls.names[func_name]['pure_inf_time']
log_interval = cls.names[func_name]['log_interval']
warmup_interval = cls.names[func_name]['warmup_interval']
with_sync = cls.names[func_name]['with_sync']
else:
count = 0
pure_inf_time = 0
cls.names[func_name] = dict(
count=count,
pure_inf_time=pure_inf_time,
log_interval=log_interval,
warmup_interval=warmup_interval,
with_sync=with_sync)
count += 1
cls.names[func_name]['count'] = count
if with_sync and torch.cuda.is_available():
torch.cuda.synchronize()
start_time = time.perf_counter()
yield
if with_sync and torch.cuda.is_available():
torch.cuda.synchronize()
elapsed = time.perf_counter() - start_time
print(f'[{func_name}]-{count} elapsed time(single interval): '
f'{(elapsed * 1000):.1f} ms',
flush=True)
if count > warmup_interval:
pure_inf_time += elapsed
cls.names[func_name]['pure_inf_time'] = pure_inf_time
if count % log_interval == 0:
times_per_count = 1000 * pure_inf_time / (
count - warmup_interval)
print(
f'[{func_name}]-{count} average time(without warnup): '
f'{times_per_count:.1f} ms',
flush=True)