Skip to content
Snippets Groups Projects
Commit 59bffdf1 authored by Cyril Moineau's avatar Cyril Moineau
Browse files

Rewrite memory manager log_info in Python.

parent a983179d
No related branches found
No related tags found
2 merge requests!318[Upd] release verision 0.5.0,!276Rewrite memory manager log_info in Python.
...@@ -5,6 +5,9 @@ from pathlib import Path ...@@ -5,6 +5,9 @@ from pathlib import Path
import aidge_core import aidge_core
from typing import Tuple, List from typing import Tuple, List
import matplotlib.pyplot as plt
import aidge_core.mem_info
import numpy as np
# Default memory management, which can be used for development # Default memory management, which can be used for development
def compute_default_mem_info(scheduler: aidge_core.Scheduler) -> Tuple[int, List]: def compute_default_mem_info(scheduler: aidge_core.Scheduler) -> Tuple[int, List]:
...@@ -41,20 +44,78 @@ def compute_default_mem_info(scheduler: aidge_core.Scheduler) -> Tuple[int, List ...@@ -41,20 +44,78 @@ def compute_default_mem_info(scheduler: aidge_core.Scheduler) -> Tuple[int, List
mem_info[node] = [] # No meminfo for producer mem_info[node] = [] # No meminfo for producer
return mem_size, mem_info return mem_size, mem_info
# TODO remove
# def _gnuplot_installed():
# try:
# # Run gnuplot with the --version flag and capture the output
# subprocess.run(["gnuplot", "--version"])
# return True
# except FileNotFoundError:
# aidge_core.Log.warn("Gnuplot is not installed.")
# return False
# except subprocess.CalledProcessError:
# aidge_core.Log.warn("Gnuplot command found but failed to run.")
# return False
def log_meminfo(mem_manager:aidge_core.MemoryManager, path: Path, diplay_names:bool):
"""Generate a graph representing the memory allocation of each ouputs.
Block with the smae color correspond to the same memory plane.
:param mem_manager: Memory manager to log
:type mem_manager: aidge_core.memory_manager
:param path: Path where to save the figure
:type path: Path
:param diplay_names: If True Node names are diplayed alongside their block
:type diplay_names: bool
"""
def _gnuplot_installed(): max_lifetime = mem_manager.get_max_lifetime()
try:
# Run gnuplot with the --version flag and capture the output # peak_usage in kwords
subprocess.run(["gnuplot", "--version"]) peak_usage = mem_manager.get_peak_usage() / 1024
return True
except FileNotFoundError: # Set figure size 1920x1080 px
aidge_core.Log.warn("Gnuplot is not installed.") plt.figure(figsize=(19.20, 10.80))
return False # Same color for each planes
except subprocess.CalledProcessError: colors = plt.cm.viridis(np.linspace(0, 1, len(mem_manager.get_planes()) + 1))
aidge_core.Log.warn("Gnuplot command found but failed to run.") color_id = 1
return False for node, planes in mem_manager.get_planes().items():
for plane in planes:
def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder: Path = None, wrapping: bool = False) -> Tuple[int, List[dict]]: cont_offset = plane.get_contiguous_offset()
cont_size = plane.get_contiguous_size()
allocated = plane.mem_space.allocated
released = plane.mem_space.released
is_released = released >= 0 and not plane.mem_space.dependencies
x_start = allocated
y_start = cont_offset / 1024.0
y_end = (cont_offset + cont_size) / 1024.0
x_end = max_lifetime if not is_released else released
plt.fill_betweenx(
[y_start, y_end],
x_start,
x_end + 1,
color=colors[color_id % len(colors)]
)
if diplay_names:
# Rotation for lisibility!
plt.text(x_end,y_end, node.name(), rotation=45)
color_id += 1
plt.axhline(y=peak_usage, color='red', linestyle='--')
plt.text(0, peak_usage, f'Peak usage = {peak_usage} KWords', color='red')
plt.xlabel("Time")
plt.ylabel("Memory usage (KWords)")
plt.title("Memory Usage Over Time")
plt.grid(True)
plt.savefig(path)
plt.close()
aidge_core.Log.notice(f"Generated memory management info at: {path}")
def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder: Path = None, wrapping: bool = False, display_names: bool=True) -> Tuple[int, List[dict]]:
"""Generates optimized memory information for a computation graph managed by a scheduler. """Generates optimized memory information for a computation graph managed by a scheduler.
This function analyzes the memory usage of a computation graph, determining the memory peak This function analyzes the memory usage of a computation graph, determining the memory peak
...@@ -70,6 +131,8 @@ def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder ...@@ -70,6 +131,8 @@ def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder
:param wrapping: Boolean flag to enable or disable wrap-around buffer optimization. :param wrapping: Boolean flag to enable or disable wrap-around buffer optimization.
Defaults to `False`. Defaults to `False`.
:type wrapping: bool, optional :type wrapping: bool, optional
:param diplay_names: If True Node names are diplayed in the memory plot alongside their block, defaults to False
:type diplay_names: bool, optional
:return: A tuple containing the peak memory size and a list of memory information for each :return: A tuple containing the peak memory size and a list of memory information for each
scheduled node. The memory information for each node includes details such as size, scheduled node. The memory information for each node includes details such as size,
offset, stride, length, count, and optional wrap-around details. offset, stride, length, count, and optional wrap-around details.
...@@ -88,18 +151,21 @@ def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder ...@@ -88,18 +151,21 @@ def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder
nodes_at_input = [n[0] for n in scheduler.graph_view().inputs()] nodes_at_input = [n[0] for n in scheduler.graph_view().inputs()]
if stats_folder is not None: if stats_folder is not None:
if _gnuplot_installed(): log_meminfo(mem_manager, Path(stats_folder) / "memory_info.png", display_names)
# Use gnuplot to generate the log # TODO remove
os.makedirs(str(Path(stats_folder) / "graph"), exist_ok=True) # if _gnuplot_installed():
mem_manager.log("memory_info") # # Use gnuplot to generate the log
os.chmod("memory_info_plot.gnu", 0o777) # os.makedirs(str(Path(stats_folder) / "graph"), exist_ok=True)
os.system("./memory_info_plot.gnu") # mem_manager.log("memory_info")
shutil.move("memory_info", str(Path(stats_folder) / "graph" / "memory_info")) # os.chmod("memory_info_plot.gnu", 0o777)
shutil.move("memory_info_plot.png", str( # os.system("./memory_info_plot.gnu")
Path(stats_folder) / "graph" / "memory_info_plot.png")) # shutil.move("memory_info", str(Path(stats_folder) / "graph" / "memory_info"))
os.remove("memory_info_plot.gnu") # shutil.move("memory_info_plot.png", str(
else: # Path(stats_folder) / "graph" / "memory_info_plot.png"))
aidge_core.Log.warn("Warning: gnuplot is not installed, could not generate stat folder.") # os.remove("memory_info_plot.gnu")
# else:
# aidge_core.Log.warn("Warning: gnuplot is not installed, could not generate stat folder.")
# In the export, we currently use an unified memory buffer whose size # In the export, we currently use an unified memory buffer whose size
# is determined by the memory peak usage # is determined by the memory peak usage
mem_size = mem_manager.get_peak_usage() mem_size = mem_manager.get_peak_usage()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment