ttnn-visualizer 0.24.0__py3-none-any.whl
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.
- ttnn_visualizer/__init__.py +4 -0
- ttnn_visualizer/app.py +193 -0
- ttnn_visualizer/bin/docker-entrypoint-web +16 -0
- ttnn_visualizer/bin/pip3-install +17 -0
- ttnn_visualizer/csv_queries.py +618 -0
- ttnn_visualizer/decorators.py +117 -0
- ttnn_visualizer/enums.py +12 -0
- ttnn_visualizer/exceptions.py +40 -0
- ttnn_visualizer/extensions.py +14 -0
- ttnn_visualizer/file_uploads.py +78 -0
- ttnn_visualizer/models.py +275 -0
- ttnn_visualizer/queries.py +388 -0
- ttnn_visualizer/remote_sqlite_setup.py +91 -0
- ttnn_visualizer/requirements.txt +24 -0
- ttnn_visualizer/serializers.py +249 -0
- ttnn_visualizer/sessions.py +245 -0
- ttnn_visualizer/settings.py +118 -0
- ttnn_visualizer/sftp_operations.py +486 -0
- ttnn_visualizer/sockets.py +118 -0
- ttnn_visualizer/ssh_client.py +85 -0
- ttnn_visualizer/static/assets/allPaths-CKt4gwo3.js +1 -0
- ttnn_visualizer/static/assets/allPathsLoader-Dzw0zTnr.js +2 -0
- ttnn_visualizer/static/assets/index-BXlT2rEV.js +5247 -0
- ttnn_visualizer/static/assets/index-CsS_OkTl.js +1 -0
- ttnn_visualizer/static/assets/index-DTKBo2Os.css +7 -0
- ttnn_visualizer/static/assets/index-DxLGmC6o.js +1 -0
- ttnn_visualizer/static/assets/site-BTBrvHC5.webmanifest +19 -0
- ttnn_visualizer/static/assets/splitPathsBySizeLoader-HHqSPeQM.js +1 -0
- ttnn_visualizer/static/favicon/android-chrome-192x192.png +0 -0
- ttnn_visualizer/static/favicon/android-chrome-512x512.png +0 -0
- ttnn_visualizer/static/favicon/favicon-32x32.png +0 -0
- ttnn_visualizer/static/favicon/favicon.svg +3 -0
- ttnn_visualizer/static/index.html +36 -0
- ttnn_visualizer/static/sample-data/cluster-desc.yaml +763 -0
- ttnn_visualizer/tests/__init__.py +4 -0
- ttnn_visualizer/tests/test_queries.py +444 -0
- ttnn_visualizer/tests/test_serializers.py +582 -0
- ttnn_visualizer/utils.py +185 -0
- ttnn_visualizer/views.py +794 -0
- ttnn_visualizer-0.24.0.dist-info/LICENSE +202 -0
- ttnn_visualizer-0.24.0.dist-info/LICENSE_understanding.txt +3 -0
- ttnn_visualizer-0.24.0.dist-info/METADATA +144 -0
- ttnn_visualizer-0.24.0.dist-info/RECORD +46 -0
- ttnn_visualizer-0.24.0.dist-info/WHEEL +5 -0
- ttnn_visualizer-0.24.0.dist-info/entry_points.txt +2 -0
- ttnn_visualizer-0.24.0.dist-info/top_level.txt +1 -0
ttnn_visualizer/utils.py
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
2
|
+
#
|
3
|
+
# SPDX-FileCopyrightText: © 2024 Tenstorrent AI ULC
|
4
|
+
|
5
|
+
import dataclasses
|
6
|
+
import enum
|
7
|
+
import json
|
8
|
+
import logging
|
9
|
+
from functools import wraps
|
10
|
+
from pathlib import Path
|
11
|
+
import time
|
12
|
+
import re
|
13
|
+
from timeit import default_timer
|
14
|
+
from typing import Callable, Optional, Dict, Any
|
15
|
+
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
LAST_SYNCED_FILE_NAME = ".last-synced"
|
19
|
+
|
20
|
+
|
21
|
+
def str_to_bool(string_value):
|
22
|
+
return string_value.lower() in ("yes", "true", "t", "1")
|
23
|
+
|
24
|
+
|
25
|
+
@dataclasses.dataclass
|
26
|
+
class SerializeableDataclass:
|
27
|
+
def to_dict(self) -> dict:
|
28
|
+
# Convert the dataclass to a dictionary and handle Enums.
|
29
|
+
return {
|
30
|
+
key: (value.value if isinstance(value, enum.Enum) else value)
|
31
|
+
for key, value in dataclasses.asdict(self).items()
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
def timer(f: Callable):
|
36
|
+
@wraps(f)
|
37
|
+
def wrapper(*args, **kwargs):
|
38
|
+
start_time = default_timer()
|
39
|
+
response = f(*args, **kwargs)
|
40
|
+
total_elapsed_time = default_timer() - start_time
|
41
|
+
logger.info(f"{f.__name__}: Elapsed time: {total_elapsed_time:0.4f} seconds")
|
42
|
+
return response
|
43
|
+
|
44
|
+
return wrapper
|
45
|
+
|
46
|
+
|
47
|
+
def get_profiler_path(profile_name, current_app, remote_connection=None):
|
48
|
+
"""
|
49
|
+
Gets the profiler path for the given profile_name.
|
50
|
+
|
51
|
+
:param profile_name: The name of the profiler directory.
|
52
|
+
:param current_app: Flask current application object.
|
53
|
+
:param report_name: Optional name of the report directory under which the profiler resides.
|
54
|
+
|
55
|
+
:return: Profiler path as a string.
|
56
|
+
"""
|
57
|
+
local_dir = Path(current_app.config["LOCAL_DATA_DIRECTORY"])
|
58
|
+
remote_dir = Path(current_app.config["REMOTE_DATA_DIRECTORY"])
|
59
|
+
|
60
|
+
# Check if there's an associated RemoteConnection
|
61
|
+
if remote_connection:
|
62
|
+
# Use the remote directory if a remote connection exists
|
63
|
+
base_dir = Path(remote_dir).joinpath(remote_connection.host)
|
64
|
+
else:
|
65
|
+
# Default to local directory if no remote connection is present
|
66
|
+
base_dir = local_dir
|
67
|
+
|
68
|
+
if not remote_connection:
|
69
|
+
profile_dir = base_dir / "profiles"
|
70
|
+
else:
|
71
|
+
profile_dir = base_dir / "profiler"
|
72
|
+
|
73
|
+
# Construct the profiler path
|
74
|
+
profiler_path = profile_dir / profile_name
|
75
|
+
|
76
|
+
return str(profiler_path)
|
77
|
+
|
78
|
+
|
79
|
+
def get_report_path(active_report, current_app, remote_connection=None):
|
80
|
+
"""
|
81
|
+
Gets the report path for the given active_report object.
|
82
|
+
:param active_report: Dictionary representing the active report.
|
83
|
+
:param current_app: Flask current application
|
84
|
+
:param remote_connection: Remote connection model instance
|
85
|
+
|
86
|
+
:return: report_path as a string
|
87
|
+
"""
|
88
|
+
database_file_name = current_app.config["SQLITE_DB_PATH"]
|
89
|
+
local_dir = current_app.config["LOCAL_DATA_DIRECTORY"]
|
90
|
+
remote_dir = current_app.config["REMOTE_DATA_DIRECTORY"]
|
91
|
+
|
92
|
+
if active_report:
|
93
|
+
# Check if there's an associated RemoteConnection
|
94
|
+
if remote_connection:
|
95
|
+
# Use the remote directory if a remote connection exists
|
96
|
+
base_dir = Path(remote_dir).joinpath(remote_connection.host)
|
97
|
+
else:
|
98
|
+
# Default to local directory if no remote connection is present
|
99
|
+
base_dir = local_dir
|
100
|
+
|
101
|
+
# Construct the full report path
|
102
|
+
report_path = Path(base_dir).joinpath(active_report.get("report_name"))
|
103
|
+
target_path = str(Path(report_path).joinpath(database_file_name))
|
104
|
+
|
105
|
+
return target_path
|
106
|
+
else:
|
107
|
+
return ""
|
108
|
+
|
109
|
+
|
110
|
+
def read_last_synced_file(directory: str) -> Optional[int]:
|
111
|
+
"""Reads the '.last-synced' file in the specified directory and returns the timestamp as an integer, or None if not found."""
|
112
|
+
last_synced_path = Path(directory) / LAST_SYNCED_FILE_NAME
|
113
|
+
|
114
|
+
# Return None if the file does not exist
|
115
|
+
if not last_synced_path.exists():
|
116
|
+
return None
|
117
|
+
|
118
|
+
# Read and return the timestamp as an integer
|
119
|
+
with last_synced_path.open("r") as file:
|
120
|
+
timestamp = int(file.read().strip())
|
121
|
+
|
122
|
+
return timestamp
|
123
|
+
|
124
|
+
|
125
|
+
def update_last_synced(directory: Path) -> None:
|
126
|
+
"""Creates a file called '.last-synced' with the current timestamp in the specified directory."""
|
127
|
+
last_synced_path = Path(directory) / LAST_SYNCED_FILE_NAME
|
128
|
+
|
129
|
+
# Get the current Unix timestamp
|
130
|
+
timestamp = int(time.time())
|
131
|
+
|
132
|
+
# Write the timestamp to the .last-synced file
|
133
|
+
with last_synced_path.open("w") as file:
|
134
|
+
logger.info(f"Updating last synced for directory {directory}")
|
135
|
+
file.write(str(timestamp))
|
136
|
+
|
137
|
+
|
138
|
+
MEMORY_CONFIG_PATTERN = re.compile(r"MemoryConfig\((.*)\)$")
|
139
|
+
MEMORY_LAYOUT_PATTERN = re.compile(r"memory_layout=([A-Za-z_:]+)")
|
140
|
+
SHARD_SPEC_PATTERN = re.compile(
|
141
|
+
r"shard_spec=ShardSpec\(grid=\{(\[.*?\])\},shape=\{(\d+),\s*(\d+)\},orientation=ShardOrientation::([A-Z_]+),halo=(\d+)\)"
|
142
|
+
)
|
143
|
+
|
144
|
+
|
145
|
+
def parse_memory_config(memory_config: Optional[str]) -> Optional[Dict[str, Any]]:
|
146
|
+
if not memory_config: # Handle None or empty string
|
147
|
+
return None
|
148
|
+
|
149
|
+
memory_config_match = MEMORY_CONFIG_PATTERN.match(memory_config)
|
150
|
+
if not memory_config_match:
|
151
|
+
return None
|
152
|
+
|
153
|
+
captured_string = memory_config_match.group(1)
|
154
|
+
|
155
|
+
memory_layout_match = MEMORY_LAYOUT_PATTERN.search(captured_string)
|
156
|
+
memory_layout = memory_layout_match.group(1) if memory_layout_match else None
|
157
|
+
|
158
|
+
shard_spec_match = SHARD_SPEC_PATTERN.search(captured_string)
|
159
|
+
if shard_spec_match:
|
160
|
+
shard_spec = {
|
161
|
+
"grid": shard_spec_match.group(1),
|
162
|
+
"shape": [int(shard_spec_match.group(2)), int(shard_spec_match.group(3))],
|
163
|
+
"orientation": shard_spec_match.group(4),
|
164
|
+
"halo": int(shard_spec_match.group(5)),
|
165
|
+
}
|
166
|
+
else:
|
167
|
+
shard_spec = "std::nullopt"
|
168
|
+
|
169
|
+
return {
|
170
|
+
"memory_layout": memory_layout,
|
171
|
+
"shard_spec": shard_spec,
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
def read_version_from_package_json() -> str:
|
176
|
+
root_directory = Path(__file__).parent.parent.parent
|
177
|
+
file_path = root_directory / "package.json"
|
178
|
+
try:
|
179
|
+
with open(file_path, "r") as file:
|
180
|
+
content = json.load(file)
|
181
|
+
return content["version"]
|
182
|
+
except FileNotFoundError:
|
183
|
+
raise FileNotFoundError(f"The file {file_path} was not found.")
|
184
|
+
except KeyError:
|
185
|
+
raise KeyError("The 'version' key was not found in the package.json file.")
|