halib 0.2.13__tar.gz → 0.2.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {halib-0.2.13 → halib-0.2.15}/PKG-INFO +5 -1
- {halib-0.2.13 → halib-0.2.15}/README.md +3 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/profiler.py +94 -7
- {halib-0.2.13 → halib-0.2.15}/halib.egg-info/PKG-INFO +5 -1
- {halib-0.2.13 → halib-0.2.15}/halib.egg-info/requires.txt +1 -0
- {halib-0.2.13 → halib-0.2.15}/setup.py +1 -1
- {halib-0.2.13 → halib-0.2.15}/.gitignore +0 -0
- {halib-0.2.13 → halib-0.2.15}/GDriveFolder.txt +0 -0
- {halib-0.2.13 → halib-0.2.15}/LICENSE.txt +0 -0
- {halib-0.2.13 → halib-0.2.15}/MANIFEST.in +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/common/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/common/common.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/common/rich_color.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/core/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/core/base_config.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/core/base_exp.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/core/param_gen.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/core/wandb_op.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/data/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/data/dataclass_util.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/data/dataset.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/data/torchloader.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/flop_calc.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/gpu_mon.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/perfcalc.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/perfmetrics.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/perf/perftb.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/viz/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/exp/viz/plot.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/csvfile.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/ipynb.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/jsonfile.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/textfile.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/videofile.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/filetype/yamlfile.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/online/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/online/gdrive.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/online/gdrive_mkdir.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/online/projectmake.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/online/tele_noti.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/system/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/system/_list_pc.csv +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/system/cmd.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/system/filesys.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/system/path.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/utils/__init__.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/utils/dict.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib/utils/list.py +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib.egg-info/SOURCES.txt +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib.egg-info/dependency_links.txt +0 -0
- {halib-0.2.13 → halib-0.2.15}/halib.egg-info/top_level.txt +0 -0
- {halib-0.2.13 → halib-0.2.15}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: halib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
4
4
|
Summary: Small library for common tasks
|
|
5
5
|
Author: Hoang Van Ha
|
|
6
6
|
Author-email: hoangvanhauit@gmail.com
|
|
@@ -41,6 +41,7 @@ Requires-Dist: tqdm
|
|
|
41
41
|
Requires-Dist: tube_dl
|
|
42
42
|
Requires-Dist: wandb
|
|
43
43
|
Requires-Dist: ipynbname
|
|
44
|
+
Requires-Dist: typed-argument-parser
|
|
44
45
|
Dynamic: author
|
|
45
46
|
Dynamic: author-email
|
|
46
47
|
Dynamic: classifier
|
|
@@ -53,6 +54,9 @@ Dynamic: summary
|
|
|
53
54
|
|
|
54
55
|
# Helper package for coding and automation
|
|
55
56
|
|
|
57
|
+
**Version 0.2.15**
|
|
58
|
+
+ update `exp.perf.profiler`: add `enabled` flag to enable/disable profiling dynamically, also add `measure` context manager to simplify measuring code blocks.
|
|
59
|
+
|
|
56
60
|
**Version 0.2.13**
|
|
57
61
|
+ reorganize packages with most changes in `research` package; also rename `research` to `exp` (package for experiment management and utilities)
|
|
58
62
|
+ update `exp/perfcalc.py` to allow save computed performance to csv file (without explicit calling method `calc_perfs`)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Helper package for coding and automation
|
|
2
2
|
|
|
3
|
+
**Version 0.2.15**
|
|
4
|
+
+ update `exp.perf.profiler`: add `enabled` flag to enable/disable profiling dynamically, also add `measure` context manager to simplify measuring code blocks.
|
|
5
|
+
|
|
3
6
|
**Version 0.2.13**
|
|
4
7
|
+ reorganize packages with most changes in `research` package; also rename `research` to `exp` (package for experiment management and utilities)
|
|
5
8
|
+ update `exp/perfcalc.py` to allow save computed performance to csv file (without explicit calling method `calc_perfs`)
|
|
@@ -1,17 +1,62 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
3
|
import json
|
|
4
|
-
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from pprint import pprint
|
|
7
6
|
from threading import Lock
|
|
7
|
+
from functools import wraps
|
|
8
8
|
from loguru import logger
|
|
9
9
|
|
|
10
|
+
# Plotting libraries
|
|
10
11
|
from plotly.subplots import make_subplots
|
|
11
12
|
import plotly.graph_objects as go
|
|
12
13
|
import plotly.express as px # for dynamic color scales
|
|
13
14
|
|
|
15
|
+
from contextlib import contextmanager
|
|
16
|
+
|
|
14
17
|
from ...common.common import ConsoleLog
|
|
18
|
+
from ...system.path import *
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ==========================================
|
|
22
|
+
# 1. The Decorator
|
|
23
|
+
# ==========================================
|
|
24
|
+
def check_enabled(func):
|
|
25
|
+
"""
|
|
26
|
+
Decorator to skip method execution if the profiler is disabled.
|
|
27
|
+
|
|
28
|
+
This acts as a 'guard clause' for the entire function. If the profiler
|
|
29
|
+
instance has 'enabled=False', the decorated function is not executed at all,
|
|
30
|
+
saving processing time and avoiding side effects.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
@wraps(func)
|
|
34
|
+
def wrapper(self, *args, **kwargs):
|
|
35
|
+
# Gracefully handle cases where 'enabled' might not be set yet (default to True)
|
|
36
|
+
# print('check_enabled called')
|
|
37
|
+
if not getattr(self, "enabled", True):
|
|
38
|
+
# print('Profiler disabled, skipping function execution.')
|
|
39
|
+
return # Exit immediately, returning None
|
|
40
|
+
return func(self, *args, **kwargs)
|
|
41
|
+
|
|
42
|
+
return wrapper
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# ==========================================
|
|
46
|
+
# 2. The Class
|
|
47
|
+
# ==========================================
|
|
48
|
+
class ContextScope:
|
|
49
|
+
"""Helper to remember the current context name so you don't have to repeat it."""
|
|
50
|
+
|
|
51
|
+
def __init__(self, profiler, ctx_name):
|
|
52
|
+
self.profiler = profiler
|
|
53
|
+
self.ctx_name = ctx_name
|
|
54
|
+
|
|
55
|
+
@contextmanager
|
|
56
|
+
def step(self, step_name):
|
|
57
|
+
# Automatically passes the stored ctx_name + the new step_name
|
|
58
|
+
with self.profiler.measure(self.ctx_name, step_name):
|
|
59
|
+
yield
|
|
15
60
|
|
|
16
61
|
|
|
17
62
|
class zProfiler:
|
|
@@ -23,13 +68,23 @@ class zProfiler:
|
|
|
23
68
|
output_file (str): Path to save the profiling report.
|
|
24
69
|
report_format (str): Output format for reports ("json" or "csv").
|
|
25
70
|
|
|
26
|
-
Example:
|
|
71
|
+
Example (using context manager):
|
|
72
|
+
prof = zProfiler()
|
|
73
|
+
with prof.measure("my_context") as ctx:
|
|
74
|
+
with ctx.step("step1"):
|
|
75
|
+
time.sleep(0.1)
|
|
76
|
+
with ctx.step("step2"):
|
|
77
|
+
time.sleep(0.2)
|
|
78
|
+
|
|
79
|
+
Example (using raw methods):
|
|
27
80
|
prof = zProfiler()
|
|
28
81
|
prof.ctx_start("my_context")
|
|
29
82
|
prof.step_start("my_context", "step1")
|
|
30
83
|
time.sleep(0.1)
|
|
31
84
|
prof.step_end("my_context", "step1")
|
|
32
85
|
prof.ctx_end("my_context")
|
|
86
|
+
|
|
87
|
+
|
|
33
88
|
"""
|
|
34
89
|
|
|
35
90
|
_instance = None
|
|
@@ -41,13 +96,24 @@ class zProfiler:
|
|
|
41
96
|
cls._instance = super().__new__(cls)
|
|
42
97
|
return cls._instance
|
|
43
98
|
|
|
44
|
-
def __init__(
|
|
45
|
-
|
|
46
|
-
|
|
99
|
+
def __init__(self, enabled=None):
|
|
100
|
+
"""
|
|
101
|
+
Args:
|
|
102
|
+
enabled (bool, optional):
|
|
103
|
+
- If True/False: Updates the enabled state immediately.
|
|
104
|
+
- If None: Keeps the current state (defaults to True on first init).
|
|
105
|
+
"""
|
|
106
|
+
# 1. First-time initialization
|
|
47
107
|
if not hasattr(self, "_initialized"):
|
|
108
|
+
self.enabled = enabled if enabled is not None else True
|
|
48
109
|
self.time_dict = {}
|
|
49
110
|
self._initialized = True
|
|
50
111
|
|
|
112
|
+
# 2. If initialized, allow updating 'enabled' ONLY if explicitly passed
|
|
113
|
+
elif enabled is not None:
|
|
114
|
+
self.enabled = enabled
|
|
115
|
+
|
|
116
|
+
@check_enabled
|
|
51
117
|
def ctx_start(self, ctx_name="ctx_default"):
|
|
52
118
|
if not isinstance(ctx_name, str) or not ctx_name:
|
|
53
119
|
raise ValueError("ctx_name must be a non-empty string")
|
|
@@ -59,6 +125,7 @@ class zProfiler:
|
|
|
59
125
|
}
|
|
60
126
|
self.time_dict[ctx_name]["report_count"] += 1
|
|
61
127
|
|
|
128
|
+
@check_enabled
|
|
62
129
|
def ctx_end(self, ctx_name="ctx_default", report_func=None):
|
|
63
130
|
if ctx_name not in self.time_dict:
|
|
64
131
|
return
|
|
@@ -67,6 +134,7 @@ class zProfiler:
|
|
|
67
134
|
self.time_dict[ctx_name]["end"] - self.time_dict[ctx_name]["start"]
|
|
68
135
|
)
|
|
69
136
|
|
|
137
|
+
@check_enabled
|
|
70
138
|
def step_start(self, ctx_name, step_name):
|
|
71
139
|
if not isinstance(step_name, str) or not step_name:
|
|
72
140
|
raise ValueError("step_name must be a non-empty string")
|
|
@@ -76,6 +144,7 @@ class zProfiler:
|
|
|
76
144
|
self.time_dict[ctx_name]["step_dict"][step_name] = []
|
|
77
145
|
self.time_dict[ctx_name]["step_dict"][step_name].append([time.perf_counter()])
|
|
78
146
|
|
|
147
|
+
@check_enabled
|
|
79
148
|
def step_end(self, ctx_name, step_name):
|
|
80
149
|
if (
|
|
81
150
|
ctx_name not in self.time_dict
|
|
@@ -84,6 +153,24 @@ class zProfiler:
|
|
|
84
153
|
return
|
|
85
154
|
self.time_dict[ctx_name]["step_dict"][step_name][-1].append(time.perf_counter())
|
|
86
155
|
|
|
156
|
+
@contextmanager
|
|
157
|
+
def measure(self, ctx_name, step_name=None):
|
|
158
|
+
if step_name is None:
|
|
159
|
+
# --- Context Mode ---
|
|
160
|
+
self.ctx_start(ctx_name)
|
|
161
|
+
try:
|
|
162
|
+
# Yield the helper object initialized with the current context name
|
|
163
|
+
yield ContextScope(self, ctx_name)
|
|
164
|
+
finally:
|
|
165
|
+
self.ctx_end(ctx_name)
|
|
166
|
+
else:
|
|
167
|
+
# --- Step Mode ---
|
|
168
|
+
self.step_start(ctx_name, step_name)
|
|
169
|
+
try:
|
|
170
|
+
yield
|
|
171
|
+
finally:
|
|
172
|
+
self.step_end(ctx_name, step_name)
|
|
173
|
+
|
|
87
174
|
def _step_dict_to_detail(self, ctx_step_dict):
|
|
88
175
|
"""
|
|
89
176
|
'ctx_step_dict': {
|
|
@@ -167,7 +254,6 @@ class zProfiler:
|
|
|
167
254
|
)
|
|
168
255
|
return report_dict
|
|
169
256
|
|
|
170
|
-
@classmethod
|
|
171
257
|
@classmethod
|
|
172
258
|
def plot_formatted_data(
|
|
173
259
|
cls, profiler_data, outdir=None, file_format="png", do_show=False, tag=""
|
|
@@ -261,7 +347,8 @@ class zProfiler:
|
|
|
261
347
|
file_prefix = ctx if len(tag_str) == 0 else f"{tag_str}_{ctx}"
|
|
262
348
|
file_path = os.path.join(outdir, f"{file_prefix}_summary.{file_format.lower()}")
|
|
263
349
|
fig.write_image(file_path)
|
|
264
|
-
|
|
350
|
+
pprint(f"Saved figure to: 🔽")
|
|
351
|
+
pprint_local_path(file_path)
|
|
265
352
|
|
|
266
353
|
results[ctx] = fig
|
|
267
354
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: halib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
4
4
|
Summary: Small library for common tasks
|
|
5
5
|
Author: Hoang Van Ha
|
|
6
6
|
Author-email: hoangvanhauit@gmail.com
|
|
@@ -41,6 +41,7 @@ Requires-Dist: tqdm
|
|
|
41
41
|
Requires-Dist: tube_dl
|
|
42
42
|
Requires-Dist: wandb
|
|
43
43
|
Requires-Dist: ipynbname
|
|
44
|
+
Requires-Dist: typed-argument-parser
|
|
44
45
|
Dynamic: author
|
|
45
46
|
Dynamic: author-email
|
|
46
47
|
Dynamic: classifier
|
|
@@ -53,6 +54,9 @@ Dynamic: summary
|
|
|
53
54
|
|
|
54
55
|
# Helper package for coding and automation
|
|
55
56
|
|
|
57
|
+
**Version 0.2.15**
|
|
58
|
+
+ update `exp.perf.profiler`: add `enabled` flag to enable/disable profiling dynamically, also add `measure` context manager to simplify measuring code blocks.
|
|
59
|
+
|
|
56
60
|
**Version 0.2.13**
|
|
57
61
|
+ reorganize packages with most changes in `research` package; also rename `research` to `exp` (package for experiment management and utilities)
|
|
58
62
|
+ update `exp/perfcalc.py` to allow save computed performance to csv file (without explicit calling method `calc_perfs`)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|