From 2d1fdc30236e99434e14a01c08976703c7132885 Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Mon, 20 Jan 2025 16:46:53 +0000 Subject: [PATCH 01/29] WIP PR 126 --- .../power_logging/model/save_model_summary.py | 70 +++++++++++++++++++ jetson/power_logging/pyproject.toml | 2 + jetson/power_logging/uv.lock | 25 ++++++- 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 jetson/power_logging/model/save_model_summary.py diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/model/save_model_summary.py new file mode 100644 index 00000000..bb25f56f --- /dev/null +++ b/jetson/power_logging/model/save_model_summary.py @@ -0,0 +1,70 @@ +import torch +from typing import Any +# from torchsummary import summary +from torchinfo import summary +# from model.lenet import LeNet + + +def load_model(model_name: str, model_repo: str) -> Any: + """Load model from Pytorch Hub. + + Args: + model_name: Name of model. + It should be same as that in Pytorch Hub. + + Raises: + ValueError: If loading model fails from PyTorch Hub + + Returns: + PyTorch model + """ + # if model_name == "lenet": + # return LeNet() + if model_name == "fcn_resnet50": + return torch.hub.load(model_repo, model_name, pretrained=True) + try: + return torch.hub.load(model_repo, model_name) + except: + raise ValueError( + f"Model name: {model_name} is most likely incorrect. " + "Please refer https://pytorch.org/hub/ to get model name." + ) + + +def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: + """ + Recursively get all layers in a pytorch model. + + Args: + model: the pytorch model to look for layers. + name_prefix: Use to identify the parents layer. Defaults to "". + + Returns: + a list of tuple containing the layer name and the layer. + """ + children = list(model.named_children()) + + if len(children) == 0: # No child + result = [(name_prefix, model)] + else: + # If have children, iterate over each child. + result = [] + for child_name, child in children: + # Recursively call get_layers on the child, appending the current + # child's name to the name_prefix. + layers = get_layers(child, name_prefix + "_" + child_name) + result.extend(layers) + + return result + +def get_layer_info(model): + model_info = {} + for layer_name, layer in get_layers(model): + model_info[layer_name] = { + "kernal_size": layer.kernel_size if hasattr(layer, "kernel_size") else None, + "stride": layer.stride if hasattr(layer, "stride") else None, + "padding": layer.padding if hasattr(layer, "padding") else None, + "type": type(layer) + } + + return model_info \ No newline at end of file diff --git a/jetson/power_logging/pyproject.toml b/jetson/power_logging/pyproject.toml index fe27d69a..372f3aad 100644 --- a/jetson/power_logging/pyproject.toml +++ b/jetson/power_logging/pyproject.toml @@ -9,6 +9,8 @@ dependencies = [ "pandas>=2.2.3", "pillow>=11.1.0", "torch==2.2.2", + "torchinfo>=1.8.0", + "torchsummary>=1.5.1", ] [dependency-groups] diff --git a/jetson/power_logging/uv.lock b/jetson/power_logging/uv.lock index f4130490..38e79955 100644 --- a/jetson/power_logging/uv.lock +++ b/jetson/power_logging/uv.lock @@ -1191,6 +1191,7 @@ version = "12.6.85" source = { registry = "https://pypi.org/simple" } wheels = [ { url = "https://files.pythonhosted.org/packages/9d/d7/c5383e47c7e9bf1c99d5bd2a8c935af2b6d705ad831a7ec5c97db4d82f4f/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a", size = 19744971 }, + { url = "https://files.pythonhosted.org/packages/31/db/dc71113d441f208cdfe7ae10d4983884e13f464a6252450693365e166dcf/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cf4eaa7d4b6b543ffd69d6abfb11efdeb2db48270d94dfd3a452c24150829e41", size = 19270338 }, ] [[package]] @@ -1383,6 +1384,8 @@ dependencies = [ { name = "pandas" }, { name = "pillow" }, { name = "torch" }, + { name = "torchinfo" }, + { name = "torchsummary" }, ] [package.dev-dependencies] @@ -1398,6 +1401,8 @@ requires-dist = [ { name = "pandas", specifier = ">=2.2.3" }, { name = "pillow", specifier = ">=11.1.0" }, { name = "torch", specifier = "==2.2.2" }, + { name = "torchinfo", specifier = ">=1.8.0" }, + { name = "torchsummary", specifier = ">=1.5.1" }, ] [package.metadata.requires-dev] @@ -1976,6 +1981,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/0e/e4e033371a7cba9da0db5ccb507a9174e41b9c29189a932d01f2f61ecfc0/torch-2.2.2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:bf9558da7d2bf7463390b3b2a61a6a3dbb0b45b161ee1dd5ec640bf579d479fc", size = 59678388 }, ] +[[package]] +name = "torchinfo" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/d9/2b811d1c0812e9ef23e6cf2dbe022becbe6c5ab065e33fd80ee05c0cd996/torchinfo-1.8.0.tar.gz", hash = "sha256:72e94b0e9a3e64dc583a8e5b7940b8938a1ac0f033f795457f27e6f4e7afa2e9", size = 25880 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/25/973bd6128381951b23cdcd8a9870c6dcfc5606cb864df8eabd82e529f9c1/torchinfo-1.8.0-py3-none-any.whl", hash = "sha256:2e911c2918603f945c26ff21a3a838d12709223dc4ccf243407bce8b6e897b46", size = 23377 }, +] + +[[package]] +name = "torchsummary" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/64/aa68ef646bcccab489cac2a85d366559df7d9d24406dbbf3344703cbe33f/torchsummary-1.5.1.tar.gz", hash = "sha256:981bf689e22e0cf7f95c746002f20a24ad26aa6b9d861134a14bc6ce92230590", size = 3749 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/18/1474d06f721b86e6a9b9d7392ad68bed711a02f3b61ac43f13c719db50a6/torchsummary-1.5.1-py3-none-any.whl", hash = "sha256:10f41d1743fb918f83293f13183f532ab1bb8f6639a1b89e5f8592ec1919a976", size = 2826 }, +] + [[package]] name = "tqdm" version = "4.67.1" @@ -1993,7 +2016,7 @@ name = "triton" version = "2.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filelock" }, + { name = "filelock", marker = "python_full_version < '3.12'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0", size = 167928356 }, From 6d9c089ec6da31829b80f0ac30a242ab80f0f962 Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Tue, 21 Jan 2025 13:04:20 +0000 Subject: [PATCH 02/29] SD-126 Console print out of JSON material asked in ticket. Needs JSON file output and cleanup --- .../power_logging/model/save_model_summary.py | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/model/save_model_summary.py index bb25f56f..9f23df32 100644 --- a/jetson/power_logging/model/save_model_summary.py +++ b/jetson/power_logging/model/save_model_summary.py @@ -1,4 +1,5 @@ import torch +import json from typing import Any # from torchsummary import summary from torchinfo import summary @@ -20,10 +21,10 @@ def load_model(model_name: str, model_repo: str) -> Any: """ # if model_name == "lenet": # return LeNet() - if model_name == "fcn_resnet50": - return torch.hub.load(model_repo, model_name, pretrained=True) + # if model_name == "fcn_resnet50": + # return torch.hub.load(model_repo, model_name, pretrained=True) try: - return torch.hub.load(model_repo, model_name) + return torch.hub.load(model_repo, model_name, pretrained=True) except: raise ValueError( f"Model name: {model_name} is most likely incorrect. " @@ -57,14 +58,45 @@ def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, t return result -def get_layer_info(model): +def get_layer_info(model, input_shape): model_info = {} - for layer_name, layer in get_layers(model): - model_info[layer_name] = { - "kernal_size": layer.kernel_size if hasattr(layer, "kernel_size") else None, - "stride": layer.stride if hasattr(layer, "stride") else None, - "padding": layer.padding if hasattr(layer, "padding") else None, - "type": type(layer) - } - - return model_info \ No newline at end of file + test = torch.randn(*input_shape) + hooks = [] + + def register_hook(layer_name): + def hook(module, input, output): + model_info[layer_name] = { + "input_shape": tuple(input[0].size()) if input else None, + "output_shape": tuple(output.size()) if output is not None else None, + "kernel_size": getattr(module, "kernel_size", None), + "stride": getattr(module, "stride", None), + "padding": getattr(module, "padding", None), + "type": module.__class__.__name__, + # "kernal_size": layer.kernel_size if hasattr(layer, "kernel_size") else None, + # "stride": layer.stride if hasattr(layer, "stride") else None, + # "padding": layer.padding if hasattr(layer, "padding") else None, + # "type": type(layer) + } + return hook + + for name, layer in model.named_modules(): + if isinstance(layer, torch.nn.Module): + hooks.append(layer.register_forward_hook(register_hook(name))) + + model.eval() + with torch.no_grad(): + _ = model(test) + + for hook in hooks: + hook.remove() + + return model_info + + +model = load_model("resnet18", "pytorch/vision:v0.10.0") +layer_info = get_layer_info(model, (1, 3, 224, 224)) + +print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False, default=str)) + + +# save to json later From 129f0456c87bc5d288394b0a1759099c25262312 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:29:47 +0000 Subject: [PATCH 03/29] Update loop to use named_children --- jetson/power_logging/model/save_model_summary.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/model/save_model_summary.py index 9f23df32..eb1cbe2c 100644 --- a/jetson/power_logging/model/save_model_summary.py +++ b/jetson/power_logging/model/save_model_summary.py @@ -78,10 +78,9 @@ def hook(module, input, output): # "type": type(layer) } return hook - - for name, layer in model.named_modules(): - if isinstance(layer, torch.nn.Module): - hooks.append(layer.register_forward_hook(register_hook(name))) + + for layer_name, layer in get_layers(model): + hooks.append(layer.register_forward_hook(register_hook(layer_name))) model.eval() with torch.no_grad(): @@ -95,6 +94,7 @@ def hook(module, input, output): model = load_model("resnet18", "pytorch/vision:v0.10.0") layer_info = get_layer_info(model, (1, 3, 224, 224)) +# print(len(layer_info)) print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False, default=str)) From 2623a30fc4790a593de86998c32a62b99cf11f6f Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Tue, 21 Jan 2025 14:32:33 +0000 Subject: [PATCH 04/29] SD-126: Code cleaned and contents saved to JSON file --- .../power_logging/model/save_model_summary.py | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/model/save_model_summary.py index eb1cbe2c..1f698cb0 100644 --- a/jetson/power_logging/model/save_model_summary.py +++ b/jetson/power_logging/model/save_model_summary.py @@ -1,10 +1,6 @@ import torch import json from typing import Any -# from torchsummary import summary -from torchinfo import summary -# from model.lenet import LeNet - def load_model(model_name: str, model_repo: str) -> Any: """Load model from Pytorch Hub. @@ -19,10 +15,6 @@ def load_model(model_name: str, model_repo: str) -> Any: Returns: PyTorch model """ - # if model_name == "lenet": - # return LeNet() - # if model_name == "fcn_resnet50": - # return torch.hub.load(model_repo, model_name, pretrained=True) try: return torch.hub.load(model_repo, model_name, pretrained=True) except: @@ -45,20 +37,27 @@ def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, t """ children = list(model.named_children()) - if len(children) == 0: # No child + if len(children) == 0: result = [(name_prefix, model)] else: - # If have children, iterate over each child. result = [] for child_name, child in children: - # Recursively call get_layers on the child, appending the current - # child's name to the name_prefix. layers = get_layers(child, name_prefix + "_" + child_name) result.extend(layers) return result def get_layer_info(model, input_shape): + """ + Get key information of all layers within a model. + + Args: + model: The pytorch model + input_shape: input size of the model + + Returns: + information about the model + """ model_info = {} test = torch.randn(*input_shape) hooks = [] @@ -72,10 +71,6 @@ def hook(module, input, output): "stride": getattr(module, "stride", None), "padding": getattr(module, "padding", None), "type": module.__class__.__name__, - # "kernal_size": layer.kernel_size if hasattr(layer, "kernel_size") else None, - # "stride": layer.stride if hasattr(layer, "stride") else None, - # "padding": layer.padding if hasattr(layer, "padding") else None, - # "type": type(layer) } return hook @@ -94,9 +89,9 @@ def hook(module, input, output): model = load_model("resnet18", "pytorch/vision:v0.10.0") layer_info = get_layer_info(model, (1, 3, 224, 224)) -# print(len(layer_info)) - -print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False, default=str)) +print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False)) -# save to json later +output = "model_summary.json" +with open(output, "w") as file: + json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) From 3d267705ac6f35721ea78f1de640fba233815434 Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Tue, 21 Jan 2025 16:31:12 +0000 Subject: [PATCH 05/29] SD-126 Code cleaned, added load_model and get_layers to common module file, added parse arguments to save_model_summary --- jetson/power_logging/model/benchmark.py | 55 +---------- jetson/power_logging/model/model_utils.py | 46 +++++++++ .../power_logging/model/save_model_summary.py | 94 ++++++++----------- 3 files changed, 88 insertions(+), 107 deletions(-) create mode 100644 jetson/power_logging/model/model_utils.py diff --git a/jetson/power_logging/model/benchmark.py b/jetson/power_logging/model/benchmark.py index ec21364d..1632e1f3 100644 --- a/jetson/power_logging/model/benchmark.py +++ b/jetson/power_logging/model/benchmark.py @@ -18,6 +18,7 @@ from model.lenet import LeNet from functools import partial +from model_utils import load_model, get_layers """ Wrapper class for Torch.cuda.event for non-CUDA supported devices @@ -68,60 +69,6 @@ class BenchmarkMetrics(BaseModel): avg_latency: float # in seconds avg_throughput: float - -def load_model(model_name: str, model_repo: str) -> Any: - """Load model from Pytorch Hub. - - Args: - model_name: Name of model. - It should be same as that in Pytorch Hub. - - Raises: - ValueError: If loading model fails from PyTorch Hub - - Returns: - PyTorch model - """ - if model_name == "lenet": - return LeNet() - if model_name == "fcn_resnet50": - return torch.hub.load(model_repo, model_name, pretrained=True) - try: - return torch.hub.load(model_repo, model_name) - except: - raise ValueError( - f"Model name: {model_name} is most likely incorrect. " - "Please refer https://pytorch.org/hub/ to get model name." - ) - - -def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: - """ - Recursively get all layers in a pytorch model. - - Args: - model: the pytorch model to look for layers. - name_prefix: Use to identify the parents layer. Defaults to "". - - Returns: - a list of tuple containing the layer name and the layer. - """ - children = list(model.named_children()) - - if len(children) == 0: # No child - result = [(name_prefix, model)] - else: - # If have children, iterate over each child. - result = [] - for child_name, child in children: - # Recursively call get_layers on the child, appending the current - # child's name to the name_prefix. - layers = get_layers(child, name_prefix + "_" + child_name) - result.extend(layers) - - return result - - def define_and_register_hooks(model, device) -> dict: """ Define and register hooks with CUDA or CPU timing. diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py new file mode 100644 index 00000000..2a2f9d76 --- /dev/null +++ b/jetson/power_logging/model/model_utils.py @@ -0,0 +1,46 @@ +import torch +from typing import Any + +def load_model(model_name: str, model_repo: str) -> Any: + """Load model from Pytorch Hub. + + Args: + model_name: Name of model. + It should be same as that in Pytorch Hub. + + Raises: + ValueError: If loading model fails from PyTorch Hub + + Returns: + PyTorch model + """ + try: + return torch.hub.load(model_repo, model_name, pretrained=True) + except: + raise ValueError( + f"Model name: {model_name} is most likely incorrect. " + "Please refer https://pytorch.org/hub/ to get model name." + ) + +def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: + """ + Recursively get all layers in a pytorch model. + + Args: + model: the pytorch model to look for layers. + name_prefix: Use to identify the parents layer. Defaults to "". + + Returns: + a list of tuple containing the layer name and the layer. + """ + children = list(model.named_children()) + + if len(children) == 0: + result = [(name_prefix, model)] + else: + result = [] + for child_name, child in children: + layers = get_layers(child, name_prefix + "_" + child_name) + result.extend(layers) + + return result \ No newline at end of file diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/model/save_model_summary.py index 1f698cb0..1acbe2ea 100644 --- a/jetson/power_logging/model/save_model_summary.py +++ b/jetson/power_logging/model/save_model_summary.py @@ -1,51 +1,8 @@ import torch import json +import argparse from typing import Any - -def load_model(model_name: str, model_repo: str) -> Any: - """Load model from Pytorch Hub. - - Args: - model_name: Name of model. - It should be same as that in Pytorch Hub. - - Raises: - ValueError: If loading model fails from PyTorch Hub - - Returns: - PyTorch model - """ - try: - return torch.hub.load(model_repo, model_name, pretrained=True) - except: - raise ValueError( - f"Model name: {model_name} is most likely incorrect. " - "Please refer https://pytorch.org/hub/ to get model name." - ) - - -def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: - """ - Recursively get all layers in a pytorch model. - - Args: - model: the pytorch model to look for layers. - name_prefix: Use to identify the parents layer. Defaults to "". - - Returns: - a list of tuple containing the layer name and the layer. - """ - children = list(model.named_children()) - - if len(children) == 0: - result = [(name_prefix, model)] - else: - result = [] - for child_name, child in children: - layers = get_layers(child, name_prefix + "_" + child_name) - result.extend(layers) - - return result +from model_utils import load_model, get_layers def get_layer_info(model, input_shape): """ @@ -87,11 +44,42 @@ def hook(module, input, output): return model_info -model = load_model("resnet18", "pytorch/vision:v0.10.0") -layer_info = get_layer_info(model, (1, 3, 224, 224)) - -print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False)) - -output = "model_summary.json" -with open(output, "w") as file: - json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) +def run(args): + model = load_model(args.model, args.model_repo) + layer_info = get_layer_info(model, args.input_shape) + + print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False)) + + output = "model_summary.json" + with open(output, "w") as file: + json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + prog="Save Model Summary", + description="Save a summary of the model after benchmarking.", + ) + parser.add_argument( + "--model", + type=str, + default="resnet18", + help="Specify name of pretrained CNN mode from PyTorch Hub." + "For more information on PyTorch Hub visit: " + "https://pytorch.org/hub/research-models", + ) + parser.add_argument( + "--model-repo", + type=str, + default="pytorch/vision:v0.10.0", + help="Specify path and version to model repository from PyTorch Hub." + ) + parser.add_argument( + "--input-shape", + type=int, + nargs="+", + default=[1, 3, 224, 224], + help="Input shape BCHW", + ) + + args = parser.parse_args() + run(args) \ No newline at end of file From f7a836dee4c7270c6f4d9a57eda18cf15789c379 Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Wed, 22 Jan 2025 12:05:49 +0000 Subject: [PATCH 06/29] SD-126: Changed to old datacollection function, removed imports from pyproject and created bash script for model summaries --- .../model/generate_model_summaries.sh | 26 +++++++++++++++++++ jetson/power_logging/model/model_utils.py | 7 ++++- jetson/power_logging/pyproject.toml | 2 -- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 jetson/power_logging/model/generate_model_summaries.sh diff --git a/jetson/power_logging/model/generate_model_summaries.sh b/jetson/power_logging/model/generate_model_summaries.sh new file mode 100644 index 00000000..023eea41 --- /dev/null +++ b/jetson/power_logging/model/generate_model_summaries.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Directory to store results +RESULT_DIR = "raw_data/prebuilt_models" + +# List of models to process +MODELS = ("alexnet" "vgg11" "vgg13" "vgg16" "vgg19" "mobilenet_v2" "mobilenet_v3_small" "mobilenet_v3_large" "resnet18" "resnet34" "resnet50" "resnet101" "resnet152" "lenet" "resnext50_32x4d" "resnext101_32x8d" "resnext101_64x4d" "convnext_tiny" "convnext_small" "convnext_base") + +PYTHON_SCRIPT = "save_model_summary.py" + +for MODEL in "${MODELS[@]}" +do + MODEL_OUTPUT_DIR="${RESULT_DIR}/${MODEL}" + OUTPUT_FILE = "${MODEL_OUTPUT_DIR}/model_summary.json" + + mkdir -p "$MODEL_OUTPUT_DIR" + + echo "Generating summary for model: $MODEL" + python "$PYTHON_SCRIPT" --model "$MODEL" --output-file "$OUTPUT_FILE" + + if [ $? -eq 0]; then + echo "Summary saved to: $OUTPUT_FILE" + else + echo "Failed to generate summary for model: $MODEL" + fi +done \ No newline at end of file diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index 2a2f9d76..eb7236e5 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -1,5 +1,6 @@ import torch from typing import Any +from model.lenet import LeNet def load_model(model_name: str, model_repo: str) -> Any: """Load model from Pytorch Hub. @@ -14,8 +15,12 @@ def load_model(model_name: str, model_repo: str) -> Any: Returns: PyTorch model """ - try: + if model_name == "lenet": + return LeNet() + if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) + try: + return torch.hub.load(model_repo, model_name) except: raise ValueError( f"Model name: {model_name} is most likely incorrect. " diff --git a/jetson/power_logging/pyproject.toml b/jetson/power_logging/pyproject.toml index 372f3aad..fe27d69a 100644 --- a/jetson/power_logging/pyproject.toml +++ b/jetson/power_logging/pyproject.toml @@ -9,8 +9,6 @@ dependencies = [ "pandas>=2.2.3", "pillow>=11.1.0", "torch==2.2.2", - "torchinfo>=1.8.0", - "torchsummary>=1.5.1", ] [dependency-groups] From 0827c54f7f034504df4b96e60c8338d8aeda76df Mon Sep 17 00:00:00 2001 From: ocarrolm Date: Wed, 22 Jan 2025 15:53:15 +0000 Subject: [PATCH 07/29] Updated script with dvc added --- .../power_logging/generate_model_summaries.sh | 53 +++++++++++++++++++ .../model/generate_model_summaries.sh | 26 --------- jetson/power_logging/model/model_utils.py | 2 +- .../raw_data/prebuilt_models.dvc | 6 +-- .../{model => }/save_model_summary.py | 14 +++-- 5 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 jetson/power_logging/generate_model_summaries.sh delete mode 100644 jetson/power_logging/model/generate_model_summaries.sh rename jetson/power_logging/{model => }/save_model_summary.py (87%) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh new file mode 100644 index 00000000..3877f6ee --- /dev/null +++ b/jetson/power_logging/generate_model_summaries.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +set -e + +export PYTHONPATH="$(pwd):$PYTHONPATH" + +# Directory to save the outputs +OUTPUT_DIR="raw_data/prebuilt_models" + +# List of models to process +MODELS=("alexnet" "vgg16" "vgg13" "vgg19" "mobilenet_v2" "mobilenet_v3_small" + "mobilenet_v3_large" "resnet18" "resnet34" "resnet50" "resnet101" + "resnet152" "lenet" "resnext50_32x4d" "resnext101_32x8d" + "resnext101_64x4d" "convnext_tiny" "convnext_small" "convnext_base") + +# Python script to run +PYTHON_SCRIPT="./save_model_summary.py" + +# Loop through each model +for MODEL in "${MODELS[@]}" +do + # Define default input shape + INPUT_SHAPE="1 3 224 224" + + # Adjust input shape for specific models + if [ "$MODEL" == "lenet" ]; then + INPUT_SHAPE="1 1 28 28" + fi + + # Define the output path for this model + MODEL_OUTPUT_DIR="${OUTPUT_DIR}/${MODEL}" + OUTPUT_FILE="${MODEL_OUTPUT_DIR}/model_summary.json" + + # Create the directory if it doesn't exist + mkdir -p "$MODEL_OUTPUT_DIR" || { echo "Failed to create directory: $MODEL_OUTPUT_DIR"; exit 1; } + + # Run the Python script and save the output + echo "Generating summary for model: $MODEL with input shape: $INPUT_SHAPE" + python "$PYTHON_SCRIPT" --model "$MODEL" --input-shape $INPUT_SHAPE --output-file "$OUTPUT_FILE" + + if [ $? -ne 0 ]; then + echo "Skipping model: $MODEL due to loading error." + continue + fi + + if [ $? -eq 0 ]; then + echo "Summary saved to: $OUTPUT_FILE" + else + echo "Failed to generate summary for model: $MODEL" + fi + +done + diff --git a/jetson/power_logging/model/generate_model_summaries.sh b/jetson/power_logging/model/generate_model_summaries.sh deleted file mode 100644 index 023eea41..00000000 --- a/jetson/power_logging/model/generate_model_summaries.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Directory to store results -RESULT_DIR = "raw_data/prebuilt_models" - -# List of models to process -MODELS = ("alexnet" "vgg11" "vgg13" "vgg16" "vgg19" "mobilenet_v2" "mobilenet_v3_small" "mobilenet_v3_large" "resnet18" "resnet34" "resnet50" "resnet101" "resnet152" "lenet" "resnext50_32x4d" "resnext101_32x8d" "resnext101_64x4d" "convnext_tiny" "convnext_small" "convnext_base") - -PYTHON_SCRIPT = "save_model_summary.py" - -for MODEL in "${MODELS[@]}" -do - MODEL_OUTPUT_DIR="${RESULT_DIR}/${MODEL}" - OUTPUT_FILE = "${MODEL_OUTPUT_DIR}/model_summary.json" - - mkdir -p "$MODEL_OUTPUT_DIR" - - echo "Generating summary for model: $MODEL" - python "$PYTHON_SCRIPT" --model "$MODEL" --output-file "$OUTPUT_FILE" - - if [ $? -eq 0]; then - echo "Summary saved to: $OUTPUT_FILE" - else - echo "Failed to generate summary for model: $MODEL" - fi -done \ No newline at end of file diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index eb7236e5..1250d03d 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -20,7 +20,7 @@ def load_model(model_name: str, model_repo: str) -> Any: if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) try: - return torch.hub.load(model_repo, model_name) + return torch.hub.load(model_repo, model_name, pretrained=True) except: raise ValueError( f"Model name: {model_name} is most likely incorrect. " diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 864842db..69298190 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: 24989e3bca3d788a1869a73785f10c13.dir - size: 5123231536 - nfiles: 85 +- md5: 46011a7c1f1cd4da234ae9ea7edaa888.dir + size: 5123001686 + nfiles: 99 hash: md5 path: prebuilt_models diff --git a/jetson/power_logging/model/save_model_summary.py b/jetson/power_logging/save_model_summary.py similarity index 87% rename from jetson/power_logging/model/save_model_summary.py rename to jetson/power_logging/save_model_summary.py index 1acbe2ea..49513347 100644 --- a/jetson/power_logging/model/save_model_summary.py +++ b/jetson/power_logging/save_model_summary.py @@ -2,7 +2,7 @@ import json import argparse from typing import Any -from model_utils import load_model, get_layers +from model.model_utils import load_model, get_layers def get_layer_info(model, input_shape): """ @@ -46,12 +46,15 @@ def hook(module, input, output): def run(args): model = load_model(args.model, args.model_repo) + if model is None: + print(f"Model skipped '{args.model}' could not be loaded.") + return + layer_info = get_layer_info(model, args.input_shape) print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False)) - output = "model_summary.json" - with open(output, "w") as file: + with open(args.output_file, "w") as file: json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) if __name__ == "__main__": @@ -80,6 +83,11 @@ def run(args): default=[1, 3, 224, 224], help="Input shape BCHW", ) + parser.add_argument( + "--output-file", + type=str, + help="Path to save model summary JSON file." + ) args = parser.parse_args() run(args) \ No newline at end of file From 2596bafcfb63a21267c2330d72a4a4bd55f56b81 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Wed, 22 Jan 2025 16:37:02 +0000 Subject: [PATCH 08/29] Try fixing corrupted DVC cache --- jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 69298190..a862824f 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: 46011a7c1f1cd4da234ae9ea7edaa888.dir - size: 5123001686 - nfiles: 99 +- md5: 7373cd7fe78562dd4b77287f61e1ac78.dir + size: 5816826218 + nfiles: 68 hash: md5 path: prebuilt_models From 62320faa1b9815529438d3849b268fb7edf8d186 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Wed, 22 Jan 2025 16:37:19 +0000 Subject: [PATCH 09/29] uv lock --- jetson/power_logging/uv.lock | 50 ++++++++++-------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/jetson/power_logging/uv.lock b/jetson/power_logging/uv.lock index 38e79955..03932fb6 100644 --- a/jetson/power_logging/uv.lock +++ b/jetson/power_logging/uv.lock @@ -364,7 +364,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ @@ -1384,8 +1384,6 @@ dependencies = [ { name = "pandas" }, { name = "pillow" }, { name = "torch" }, - { name = "torchinfo" }, - { name = "torchsummary" }, ] [package.dev-dependencies] @@ -1401,8 +1399,6 @@ requires-dist = [ { name = "pandas", specifier = ">=2.2.3" }, { name = "pillow", specifier = ">=11.1.0" }, { name = "torch", specifier = "==2.2.2" }, - { name = "torchinfo", specifier = ">=1.8.0" }, - { name = "torchsummary", specifier = ">=1.5.1" }, ] [package.metadata.requires-dev] @@ -1953,19 +1949,19 @@ dependencies = [ { name = "fsspec" }, { name = "jinja2" }, { name = "networkx" }, - { name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, - { name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, + { name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" }, { name = "sympy" }, - { name = "triton", marker = "python_full_version < '3.12' and platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "triton", marker = "python_full_version < '3.12' and platform_machine == 'x86_64' and platform_system == 'Linux'" }, { name = "typing-extensions" }, ] wheels = [ @@ -1981,30 +1977,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/0e/e4e033371a7cba9da0db5ccb507a9174e41b9c29189a932d01f2f61ecfc0/torch-2.2.2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:bf9558da7d2bf7463390b3b2a61a6a3dbb0b45b161ee1dd5ec640bf579d479fc", size = 59678388 }, ] -[[package]] -name = "torchinfo" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/d9/2b811d1c0812e9ef23e6cf2dbe022becbe6c5ab065e33fd80ee05c0cd996/torchinfo-1.8.0.tar.gz", hash = "sha256:72e94b0e9a3e64dc583a8e5b7940b8938a1ac0f033f795457f27e6f4e7afa2e9", size = 25880 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/72/25/973bd6128381951b23cdcd8a9870c6dcfc5606cb864df8eabd82e529f9c1/torchinfo-1.8.0-py3-none-any.whl", hash = "sha256:2e911c2918603f945c26ff21a3a838d12709223dc4ccf243407bce8b6e897b46", size = 23377 }, -] - -[[package]] -name = "torchsummary" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/64/aa68ef646bcccab489cac2a85d366559df7d9d24406dbbf3344703cbe33f/torchsummary-1.5.1.tar.gz", hash = "sha256:981bf689e22e0cf7f95c746002f20a24ad26aa6b9d861134a14bc6ce92230590", size = 3749 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/18/1474d06f721b86e6a9b9d7392ad68bed711a02f3b61ac43f13c719db50a6/torchsummary-1.5.1-py3-none-any.whl", hash = "sha256:10f41d1743fb918f83293f13183f532ab1bb8f6639a1b89e5f8592ec1919a976", size = 2826 }, -] - [[package]] name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ From b1827ee395d9299b86381f75306119cf837f0d18 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 09:35:34 +0000 Subject: [PATCH 10/29] Fix imports --- jetson/power_logging/model/benchmark.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jetson/power_logging/model/benchmark.py b/jetson/power_logging/model/benchmark.py index 1632e1f3..1d3fd7e1 100644 --- a/jetson/power_logging/model/benchmark.py +++ b/jetson/power_logging/model/benchmark.py @@ -11,14 +11,12 @@ from pathlib import Path from typing import Any -import numpy as np import torch from pydantic import BaseModel from tqdm import tqdm -from model.lenet import LeNet from functools import partial -from model_utils import load_model, get_layers +from model.model_utils import load_model, get_layers """ Wrapper class for Torch.cuda.event for non-CUDA supported devices From e7b1d3803c2173127631030d9d1b0bfdc995c76a Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 09:53:31 +0000 Subject: [PATCH 11/29] Add partial data to DVC --- jetson/power_logging/generate_model_summaries.sh | 0 jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 jetson/power_logging/generate_model_summaries.sh diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh old mode 100644 new mode 100755 diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index a862824f..05e39b34 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: 7373cd7fe78562dd4b77287f61e1ac78.dir - size: 5816826218 - nfiles: 68 +- md5: 6f12ce3342e5c5276ad1db749fa86d75.dir + size: 5816816222 + nfiles: 67 hash: md5 path: prebuilt_models From cebcb44d503c9b25e660f6781dfe8982d5101dc4 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 10:34:56 +0000 Subject: [PATCH 12/29] Specify weights when loading --- jetson/power_logging/model/model_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index 1250d03d..f492942c 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -20,7 +20,7 @@ def load_model(model_name: str, model_repo: str) -> Any: if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) try: - return torch.hub.load(model_repo, model_name, pretrained=True) + return torch.hub.load(model_repo, model_name, weights="IMAGENET1K_V1") except: raise ValueError( f"Model name: {model_name} is most likely incorrect. " From 0779eb159600970df31dd2bdd59b155057669c49 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 13:47:50 +0000 Subject: [PATCH 13/29] Remove prebuilt models measurements from this branch --- jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 05e39b34..372c90a7 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: 6f12ce3342e5c5276ad1db749fa86d75.dir - size: 5816816222 - nfiles: 67 +- md5: d751713988987e9331980363e24189ce.dir + size: 0 + nfiles: 0 hash: md5 path: prebuilt_models From 60cb54aeeff60ebb7fdc6f595070b9ecace428fb Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 14:05:53 +0000 Subject: [PATCH 14/29] Regenerate date with a different indentation, to avoid the corrupted cache files --- jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 372c90a7..7f496cb4 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: d751713988987e9331980363e24189ce.dir - size: 0 - nfiles: 0 +- md5: b402c116d7026e968f2efd29e6e0b4b9.dir + size: 5816628302 + nfiles: 67 hash: md5 path: prebuilt_models From c75d7b00da8147a6ddef30efb4916f19550535dd Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 14:15:29 +0000 Subject: [PATCH 15/29] Regenerate date with a different indentation, to avoid the corrupted cache files --- jetson/power_logging/generate_model_summaries.sh | 2 +- jetson/power_logging/model/model_utils.py | 2 +- jetson/power_logging/save_model_summary.py | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh index 3877f6ee..934047e3 100755 --- a/jetson/power_logging/generate_model_summaries.sh +++ b/jetson/power_logging/generate_model_summaries.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -e +#set -e export PYTHONPATH="$(pwd):$PYTHONPATH" diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index f492942c..eb7236e5 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -20,7 +20,7 @@ def load_model(model_name: str, model_repo: str) -> Any: if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) try: - return torch.hub.load(model_repo, model_name, weights="IMAGENET1K_V1") + return torch.hub.load(model_repo, model_name) except: raise ValueError( f"Model name: {model_name} is most likely incorrect. " diff --git a/jetson/power_logging/save_model_summary.py b/jetson/power_logging/save_model_summary.py index 49513347..00a3cceb 100644 --- a/jetson/power_logging/save_model_summary.py +++ b/jetson/power_logging/save_model_summary.py @@ -52,10 +52,8 @@ def run(args): layer_info = get_layer_info(model, args.input_shape) - print(json.dumps(layer_info, indent=4, separators=(",", ": "), ensure_ascii=False)) - with open(args.output_file, "w") as file: - json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) + json.dump(layer_info, file, indent=2) if __name__ == "__main__": parser = argparse.ArgumentParser( From c69ba76f17127dd2151b442f47b21d3a071b554c Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:29:44 +0000 Subject: [PATCH 16/29] Test model loading --- jetson/power_logging/model/model_utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index eb7236e5..8a75ee4a 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -1,6 +1,6 @@ import torch from typing import Any -from model.lenet import LeNet +# from model.lenet import LeNet def load_model(model_name: str, model_repo: str) -> Any: """Load model from Pytorch Hub. @@ -15,8 +15,8 @@ def load_model(model_name: str, model_repo: str) -> Any: Returns: PyTorch model """ - if model_name == "lenet": - return LeNet() + # if model_name == "lenet": + # return LeNet() if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) try: @@ -27,6 +27,8 @@ def load_model(model_name: str, model_repo: str) -> Any: "Please refer https://pytorch.org/hub/ to get model name." ) +model = load_model("convnext_base", "pytorch/vision") + def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: """ Recursively get all layers in a pytorch model. From caae6e6e6a383ed90b1938c27c49387bb06aadf9 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:47:50 +0000 Subject: [PATCH 17/29] Test --- jetson/power_logging/model/model_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index 8a75ee4a..2bde632f 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -27,7 +27,7 @@ def load_model(model_name: str, model_repo: str) -> Any: "Please refer https://pytorch.org/hub/ to get model name." ) -model = load_model("convnext_base", "pytorch/vision") +model = load_model("convnext_base", "pytorch/vision", force_reload=True) def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: """ From 668505b21586f7444846699939b03c85c3af56d0 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:48:46 +0000 Subject: [PATCH 18/29] Test torch hub endpoitns --- jetson/power_logging/model/model_utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index 2bde632f..682aaf1c 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -27,7 +27,9 @@ def load_model(model_name: str, model_repo: str) -> Any: "Please refer https://pytorch.org/hub/ to get model name." ) -model = load_model("convnext_base", "pytorch/vision", force_reload=True) +entrypoints = torch.hub.list("pytorch/vision", force_reload=True) +print(entrypoints) +model = load_model("convnext_base", "pytorch/vision") def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: """ From 65459ba02e651252606f6b95abe8b0681fc04fd6 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:50:50 +0000 Subject: [PATCH 19/29] Test with version --- jetson/power_logging/model/model_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index 682aaf1c..ef4a321a 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -26,10 +26,11 @@ def load_model(model_name: str, model_repo: str) -> Any: f"Model name: {model_name} is most likely incorrect. " "Please refer https://pytorch.org/hub/ to get model name." ) - -entrypoints = torch.hub.list("pytorch/vision", force_reload=True) + +print(torch.__version__) +entrypoints = torch.hub.list("pytorch/vision:v0.10.0", force_reload=True) print(entrypoints) -model = load_model("convnext_base", "pytorch/vision") +model = load_model("convnext_base", "pytorch/vision:v0.10.0") def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: """ From 313099d63ae389a1873066c52ede44171014a936 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:04:29 +0000 Subject: [PATCH 20/29] Update working torch model repo version --- jetson/power_logging/model/model_utils.py | 10 +++------- jetson/power_logging/save_model_summary.py | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/jetson/power_logging/model/model_utils.py b/jetson/power_logging/model/model_utils.py index ef4a321a..275ddeee 100644 --- a/jetson/power_logging/model/model_utils.py +++ b/jetson/power_logging/model/model_utils.py @@ -1,6 +1,6 @@ import torch from typing import Any -# from model.lenet import LeNet +from model.lenet import LeNet def load_model(model_name: str, model_repo: str) -> Any: """Load model from Pytorch Hub. @@ -15,8 +15,8 @@ def load_model(model_name: str, model_repo: str) -> Any: Returns: PyTorch model """ - # if model_name == "lenet": - # return LeNet() + if model_name == "lenet": + return LeNet() if model_name == "fcn_resnet50": return torch.hub.load(model_repo, model_name, pretrained=True) try: @@ -27,10 +27,6 @@ def load_model(model_name: str, model_repo: str) -> Any: "Please refer https://pytorch.org/hub/ to get model name." ) -print(torch.__version__) -entrypoints = torch.hub.list("pytorch/vision:v0.10.0", force_reload=True) -print(entrypoints) -model = load_model("convnext_base", "pytorch/vision:v0.10.0") def get_layers(model: torch.nn.Module, name_prefix: str="") -> list[tuple[str, torch.nn.Module]]: """ diff --git a/jetson/power_logging/save_model_summary.py b/jetson/power_logging/save_model_summary.py index 00a3cceb..66d0e67c 100644 --- a/jetson/power_logging/save_model_summary.py +++ b/jetson/power_logging/save_model_summary.py @@ -71,7 +71,7 @@ def run(args): parser.add_argument( "--model-repo", type=str, - default="pytorch/vision:v0.10.0", + default="pytorch/vision:v0.16.0", help="Specify path and version to model repository from PyTorch Hub." ) parser.add_argument( From e173da3658c44e7e70d5aff873a9e02509b815b8 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 15:37:07 +0000 Subject: [PATCH 21/29] Add test file --- jetson/power_logging/raw_data/.gitignore | 1 + jetson/power_logging/raw_data/test_file.json.dvc | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 jetson/power_logging/raw_data/test_file.json.dvc diff --git a/jetson/power_logging/raw_data/.gitignore b/jetson/power_logging/raw_data/.gitignore index 1c261996..461d40d9 100644 --- a/jetson/power_logging/raw_data/.gitignore +++ b/jetson/power_logging/raw_data/.gitignore @@ -1 +1,2 @@ /prebuilt_models +/test_file.json diff --git a/jetson/power_logging/raw_data/test_file.json.dvc b/jetson/power_logging/raw_data/test_file.json.dvc new file mode 100644 index 00000000..d0f72c0e --- /dev/null +++ b/jetson/power_logging/raw_data/test_file.json.dvc @@ -0,0 +1,5 @@ +outs: +- md5: d8e8fca2dc0f896fd7cb4cb0031ba249 + size: 5 + hash: md5 + path: test_file.json From c79ea8b86bc685275f2da4438c652d8fce29b0a9 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:44:45 +0000 Subject: [PATCH 22/29] Another test --- jetson/power_logging/raw_data/.gitignore | 1 + jetson/power_logging/raw_data/another_test.json.dvc | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 jetson/power_logging/raw_data/another_test.json.dvc diff --git a/jetson/power_logging/raw_data/.gitignore b/jetson/power_logging/raw_data/.gitignore index 461d40d9..17730673 100644 --- a/jetson/power_logging/raw_data/.gitignore +++ b/jetson/power_logging/raw_data/.gitignore @@ -1,2 +1,3 @@ /prebuilt_models /test_file.json +/another_test.json diff --git a/jetson/power_logging/raw_data/another_test.json.dvc b/jetson/power_logging/raw_data/another_test.json.dvc new file mode 100644 index 00000000..444bd636 --- /dev/null +++ b/jetson/power_logging/raw_data/another_test.json.dvc @@ -0,0 +1,5 @@ +outs: +- md5: 7d980e6be82dd33893f39d652d8a99a1 + size: 13 + hash: md5 + path: another_test.json From b164482b9438fca1800f8bf53fda43d222a36fb0 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:52:57 +0000 Subject: [PATCH 23/29] Fix lenet input dimensions --- jetson/power_logging/generate_model_summaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh index 934047e3..e7e93365 100755 --- a/jetson/power_logging/generate_model_summaries.sh +++ b/jetson/power_logging/generate_model_summaries.sh @@ -24,7 +24,7 @@ do # Adjust input shape for specific models if [ "$MODEL" == "lenet" ]; then - INPUT_SHAPE="1 1 28 28" + INPUT_SHAPE="1 1 32 32" fi # Define the output path for this model From a33d191b8adf84f7d8675770d4663a5947c9b0d6 Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:53:32 +0000 Subject: [PATCH 24/29] Add model summaries collected on the jetson --- jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 7f496cb4..43d63426 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: b402c116d7026e968f2efd29e6e0b4b9.dir - size: 5816628302 - nfiles: 67 +- md5: ea1a4861ca0bd66a6ef6c8cce9de24c4.dir + size: 776946 + nfiles: 19 hash: md5 path: prebuilt_models From 773e00bcbf18d70d92b631049722b3f9ff5de9d7 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 15:55:39 +0000 Subject: [PATCH 25/29] Remove test files --- jetson/power_logging/raw_data/.gitignore | 2 -- jetson/power_logging/raw_data/another_test.json.dvc | 5 ----- jetson/power_logging/raw_data/test_file.json.dvc | 5 ----- 3 files changed, 12 deletions(-) delete mode 100644 jetson/power_logging/raw_data/another_test.json.dvc delete mode 100644 jetson/power_logging/raw_data/test_file.json.dvc diff --git a/jetson/power_logging/raw_data/.gitignore b/jetson/power_logging/raw_data/.gitignore index 17730673..1c261996 100644 --- a/jetson/power_logging/raw_data/.gitignore +++ b/jetson/power_logging/raw_data/.gitignore @@ -1,3 +1 @@ /prebuilt_models -/test_file.json -/another_test.json diff --git a/jetson/power_logging/raw_data/another_test.json.dvc b/jetson/power_logging/raw_data/another_test.json.dvc deleted file mode 100644 index 444bd636..00000000 --- a/jetson/power_logging/raw_data/another_test.json.dvc +++ /dev/null @@ -1,5 +0,0 @@ -outs: -- md5: 7d980e6be82dd33893f39d652d8a99a1 - size: 13 - hash: md5 - path: another_test.json diff --git a/jetson/power_logging/raw_data/test_file.json.dvc b/jetson/power_logging/raw_data/test_file.json.dvc deleted file mode 100644 index d0f72c0e..00000000 --- a/jetson/power_logging/raw_data/test_file.json.dvc +++ /dev/null @@ -1,5 +0,0 @@ -outs: -- md5: d8e8fca2dc0f896fd7cb4cb0031ba249 - size: 5 - hash: md5 - path: test_file.json From 0a10fe67944615361e7940d6f95f0051ecee9e0b Mon Sep 17 00:00:00 2001 From: osw282 <25309418+osw282@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:13:06 +0000 Subject: [PATCH 26/29] Fixed data collected on jetson --- jetson/power_logging/raw_data/prebuilt_models.dvc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/raw_data/prebuilt_models.dvc b/jetson/power_logging/raw_data/prebuilt_models.dvc index 43d63426..058ba499 100644 --- a/jetson/power_logging/raw_data/prebuilt_models.dvc +++ b/jetson/power_logging/raw_data/prebuilt_models.dvc @@ -1,6 +1,6 @@ outs: -- md5: ea1a4861ca0bd66a6ef6c8cce9de24c4.dir - size: 776946 - nfiles: 19 +- md5: 231fccd47cc6bc83a77723fea529bf46.dir + size: 5816901659 + nfiles: 72 hash: md5 path: prebuilt_models From 3d4747190af6b19b65535c67387cbfc1e9a8e89f Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Thu, 23 Jan 2025 16:16:34 +0000 Subject: [PATCH 27/29] Revert some unnecessary changes --- jetson/power_logging/generate_model_summaries.sh | 2 +- jetson/power_logging/save_model_summary.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh index e7e93365..989b8773 100755 --- a/jetson/power_logging/generate_model_summaries.sh +++ b/jetson/power_logging/generate_model_summaries.sh @@ -1,6 +1,6 @@ #!/bin/bash -#set -e +set -e export PYTHONPATH="$(pwd):$PYTHONPATH" diff --git a/jetson/power_logging/save_model_summary.py b/jetson/power_logging/save_model_summary.py index 66d0e67c..730834f1 100644 --- a/jetson/power_logging/save_model_summary.py +++ b/jetson/power_logging/save_model_summary.py @@ -53,7 +53,7 @@ def run(args): layer_info = get_layer_info(model, args.input_shape) with open(args.output_file, "w") as file: - json.dump(layer_info, file, indent=2) + json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) if __name__ == "__main__": parser = argparse.ArgumentParser( From 67436b1dd2d04ef91ba362bbf62e28dc79c56be8 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Fri, 24 Jan 2025 11:53:41 +0000 Subject: [PATCH 28/29] Address comments --- jetson/power_logging/generate_model_summaries.sh | 4 +--- jetson/power_logging/save_model_summary.py | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh index 989b8773..e41d62b5 100755 --- a/jetson/power_logging/generate_model_summaries.sh +++ b/jetson/power_logging/generate_model_summaries.sh @@ -1,8 +1,6 @@ #!/bin/bash -set -e - -export PYTHONPATH="$(pwd):$PYTHONPATH" +set -eou pipefail # Directory to save the outputs OUTPUT_DIR="raw_data/prebuilt_models" diff --git a/jetson/power_logging/save_model_summary.py b/jetson/power_logging/save_model_summary.py index 730834f1..fe519f70 100644 --- a/jetson/power_logging/save_model_summary.py +++ b/jetson/power_logging/save_model_summary.py @@ -1,3 +1,5 @@ +from pathlib import Path + import torch import json import argparse @@ -52,6 +54,7 @@ def run(args): layer_info = get_layer_info(model, args.input_shape) + Path(args.output_file).parent.mkdir(parents=True, exist_ok=True) with open(args.output_file, "w") as file: json.dump(layer_info, file, indent=4, separators=(",", ": "), ensure_ascii=False) From 05554c2d3d9eca9598f5eee16e5f1f7977728f24 Mon Sep 17 00:00:00 2001 From: Misha Iakovlev Date: Fri, 24 Jan 2025 11:55:09 +0000 Subject: [PATCH 29/29] Address comments --- jetson/power_logging/generate_model_summaries.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/jetson/power_logging/generate_model_summaries.sh b/jetson/power_logging/generate_model_summaries.sh index e41d62b5..1be9eded 100755 --- a/jetson/power_logging/generate_model_summaries.sh +++ b/jetson/power_logging/generate_model_summaries.sh @@ -29,9 +29,6 @@ do MODEL_OUTPUT_DIR="${OUTPUT_DIR}/${MODEL}" OUTPUT_FILE="${MODEL_OUTPUT_DIR}/model_summary.json" - # Create the directory if it doesn't exist - mkdir -p "$MODEL_OUTPUT_DIR" || { echo "Failed to create directory: $MODEL_OUTPUT_DIR"; exit 1; } - # Run the Python script and save the output echo "Generating summary for model: $MODEL with input shape: $INPUT_SHAPE" python "$PYTHON_SCRIPT" --model "$MODEL" --input-shape $INPUT_SHAPE --output-file "$OUTPUT_FILE"