66import colorsys
77import sys
88import scipy .stats
9+ from collections import defaultdict
910
1011SHOW_TITLES = False
1112
1718})
1819
1920# Constants
20- PEAK_BASE = 6 # Subtracted from peak memory values (in MB)
21- PEAK_THRESHOLD = 6 # Minimum required baseline peak after subtraction (in MB)
21+ PEAK_BASE = 5.5 # Subtracted from peak memory values (in MB)
22+ PEAK_THRESHOLD = 5 # Minimum required baseline peak after subtraction (in MB)
2223
2324ROOT_DIR = "/home/thomas/tweag/tbagrel-phd-manuscript/graphics/"
2425
@@ -61,6 +62,48 @@ def compute_fallback_baseline(size, methods, alloc_pivot, copied_pivot, mean_all
6162 denom += r_alloc ** 2 #+ r_copied**2
6263 return num / denom if denom > 0 else np .nan
6364
65+ def apply_global_offset_to_all_points (x_series_list , y_series_list , offset_ratio = 0.005 ):
66+ """
67+ Applies vertical offsets to avoid overlapping (x, y) points globally,
68+ with offset proportional to the overall y-range of all data combined.
69+
70+ Parameters:
71+ - x_series_list: list of x arrays (one per series)
72+ - y_series_list: list of y arrays (one per series)
73+ - offset_ratio: fraction of global y-range used as offset magnitude
74+ """
75+ from collections import defaultdict
76+ import numpy as np
77+
78+ # Flatten all points with (x, y, series_index, point_index)
79+ all_points = []
80+ for series_index , (xs , ys ) in enumerate (zip (x_series_list , y_series_list )):
81+ for point_index , (x , y ) in enumerate (zip (xs , ys )):
82+ all_points .append ((x , y , series_index , point_index ))
83+
84+ # Group points by exact (x, y)
85+ point_groups = defaultdict (list )
86+ for pt in all_points :
87+ key = (pt [0 ], pt [1 ])
88+ point_groups [key ].append (pt )
89+
90+ # Compute global y-range over all points
91+ all_y = np .concatenate ([np .array (ys ) for ys in y_series_list ])
92+ y_range = np .ptp (all_y ) # peak-to-peak range
93+ abs_offset = offset_ratio * y_range if y_range > 0 else offset_ratio
94+
95+ # Prepare adjusted copies
96+ adjusted_series_list = [np .array (ys ).copy () for ys in y_series_list ]
97+
98+ # Apply symmetric offsets to overlapping points
99+ for group in point_groups .values ():
100+ if len (group ) > 1 :
101+ for j , (x , y , series_idx , point_idx ) in enumerate (group ):
102+ delta = abs_offset * (j - (len (group ) - 1 ) / 2 )
103+ adjusted_series_list [series_idx ][point_idx ] += delta
104+
105+ return adjusted_series_list
106+
64107def draw (df , test_description , methods , method_baseline , title , output_file = None ):
65108 # Start fresh
66109 plt .close ('all' )
@@ -126,15 +169,23 @@ def draw(df, test_description, methods, method_baseline, title, output_file=None
126169 fig , (ax1 , ax2 ) = plt .subplots (1 , 2 , figsize = (15 , 7.5 ), sharex = False )
127170
128171 # --- Time plot (all sizes included) ---
172+ rel_time_series = []
129173 for method in methods :
130174 rel_time = time_pivot [method ] / time_pivot [method_baseline ]
131- ax1 .plot (time_pivot .index , rel_time , marker = 'o' , color = method_colors [method ],
132- label = f"\\ texttt{{{ method } }}" , linewidth = 1.5 , alpha = 1.0 )
175+ rel_time_series .append (np .array (rel_time ))
176+
177+ # Compute adjusted values with cross-method offset
178+ rel_time_adjusted_list = apply_global_offset_to_all_points ([time_pivot .index ]* (len (rel_time_series )), rel_time_series )
179+
180+ # Now plot each method with its adjusted y-values
181+ for method , rel_time_adjusted in zip (methods , rel_time_adjusted_list ):
182+ ax1 .plot (time_pivot .index , rel_time_adjusted , marker = 'o' , color = method_colors [method ],
183+ label = f"\\ texttt{{{ method } }}" , linewidth = 2 , alpha = 1.0 )
133184
134185 ax1 .set_xscale ("log" , base = 2 )
135186 ax1 .set_xticks (xticks )
136187 ax1 .set_xticklabels (xtick_labels )
137- ax1 .axhline (1.0 , color = 'gray' , linestyle = '--' , linewidth = 1 )
188+ # ax1.axhline(1.0, color='gray', linestyle='--', linewidth=1)
138189 ax1 .set_ylabel (f"Relative time in \\ textit{{ms}} (vs. \\ texttt{{{ method_baseline } }})" )
139190 ax1 .set_xlabel ("Input size (nb. of elements)" )
140191 ax1 .set_title ("Time (lower is better)" )
@@ -144,9 +195,14 @@ def draw(df, test_description, methods, method_baseline, title, output_file=None
144195 # --- Memory plot ---
145196
146197 sizes = sorted (set (filtered_df ["SizeNum" ]))
198+
199+ x_series_all = []
200+ y_series_all = []
201+ plot_metadata = [] # to keep (method, type, x_series)
202+
147203 for method in methods :
148204 color = method_colors [method ]
149- style = {'linewidth' : 1.5 , 'alpha' : 1.0 }
205+ style = {'linewidth' : 2 , 'alpha' : 1.0 }
150206
151207 peak_points_x , peak_points_y = [], []
152208 alloc_points_x , alloc_points_y = [], []
@@ -196,18 +252,28 @@ def draw(df, test_description, methods, method_baseline, title, output_file=None
196252 peak_points_x .append (size )
197253 peak_points_y .append (peak_val / baseline )
198254
199- # Plot all collected points
200- ax2 .plot (peak_points_x , peak_points_y , marker = 'o' , linestyle = '-' , color = color ,
201- label = f"\\ texttt{{{ method } }} peak" , ** style )
202- ax2 .plot (alloc_points_x , alloc_points_y , marker = '+' , linestyle = '--' , color = color ,
203- label = f"\\ texttt{{{ method } }} allocated" , ** style )
204- ax2 .plot (copied_points_x , copied_points_y , marker = 'd' , linestyle = ':' , color = color ,
205- label = f"\\ texttt{{{ method } }} copied" , ** style )
255+ color = method_colors [method ]
256+
257+ # Append to unified list
258+ x_series_all .extend ([peak_points_x , alloc_points_x , copied_points_x ])
259+ y_series_all .extend ([peak_points_y , alloc_points_y , copied_points_y ])
260+ plot_metadata .extend ([
261+ (method , 'peak' , peak_points_x , 'o' , '-' , color ),
262+ (method , 'allocated' , alloc_points_x , '+' , '--' , color ),
263+ (method , 'copied' , copied_points_x , 'd' , ':' , color ),
264+ ])
265+
266+ adjusted_y_all = apply_global_offset_to_all_points (x_series_all , y_series_all )
267+
268+ # Plot each adjusted series
269+ for adjusted_y , (method , label , x_vals , marker , linestyle , color ) in zip (adjusted_y_all , plot_metadata ):
270+ ax2 .plot (x_vals , adjusted_y , marker = marker , linestyle = linestyle , color = color ,
271+ label = f"\\ texttt{{{ method } }} { label } " , ** style )
206272
207273 ax2 .set_xscale ("log" , base = 2 )
208274 ax2 .set_xticks (xticks )
209275 ax2 .set_xticklabels (xtick_labels )
210- ax2 .axhline (1.0 , color = 'gray' , linestyle = '--' , linewidth = 1 )
276+ # ax2.axhline(1.0, color='gray', linestyle='--', linewidth=1)
211277 ax2 .set_ylabel (f"Relative memory usage in \\ textit{{MB}} (vs. \\ texttt{{{ method_baseline } }} peak)" )
212278 ax2 .set_xlabel ("Input size (nb. of elements)" )
213279 ax2 .set_title ("Memory (lower is better)" )
@@ -257,7 +323,7 @@ def draw(df, test_description, methods, method_baseline, title, output_file=None
257323 # "mapS.force",
258324 # "mapS.copyCR",
259325 "mapSH.force" ,
260- # "mapSH.copyCR",
326+ "mapSH.copyCR" ,
261327 # "mapST.force",
262328 # "mapST.copyCR",
263329 # "mapTRL.force",
0 commit comments