2828
2929import matplotlib .pyplot as plt
3030import pandas as pd
31- from loguru import logger
31+ try :
32+ from loguru import logger # type: ignore
33+ except ModuleNotFoundError : # pragma: no cover
34+ import logging
35+
36+ logging .basicConfig (level = logging .INFO )
37+ logger = logging .getLogger (__name__ )
3238
3339
3440# Define plotting functions
@@ -89,6 +95,97 @@ def plot_threads_vs_latency_and_save(df, output_file, title_prefix):
8995 plt .savefig (output_file )
9096 plt .close ()
9197
98+ def plot_threads_vs_bw_latency_and_save (df , output_file , title_prefix ):
99+ # Combined plot:
100+ # - X axis: Number of Threads
101+ # - Left Y axis (blue): Bandwidth
102+ # - Right Y axis (red): Latency
103+ grouped = df .groupby (["Access Type" ])
104+ access_types = list (grouped .groups .keys ())
105+
106+ fig , ax_bw = plt .subplots (figsize = (10 , 6 ))
107+ ax_lat = ax_bw .twinx ()
108+
109+ bw_handles = []
110+ lat_handles = []
111+ legend_labels = []
112+
113+ single_access_type = len (access_types ) == 1
114+
115+ for (access_type ), group in grouped :
116+ group_sorted = group .sort_values ("Threads" )
117+ threads = group_sorted ["Threads" ]
118+ bandwidth = group_sorted ["Total Bandwidth (MiB/s)" ] / 1024 # GiB/s
119+ latency = group_sorted ["Measured Latency (ns)" ]
120+
121+ if single_access_type :
122+ (bw_line ,) = ax_bw .plot (
123+ threads ,
124+ bandwidth ,
125+ marker = "o" ,
126+ linestyle = "-" ,
127+ linewidth = 3 ,
128+ color = "tab:blue" ,
129+ )
130+ (lat_line ,) = ax_lat .plot (
131+ threads ,
132+ latency ,
133+ marker = "x" ,
134+ linestyle = "--" ,
135+ linewidth = 3 ,
136+ color = "tab:red" ,
137+ )
138+ bw_handles .append (bw_line )
139+ lat_handles .append (lat_line )
140+ legend_labels .extend (["Bandwidth" , "Latency" ])
141+ else :
142+ # Keep a consistent color per access_type across both axes.
143+ (bw_line ,) = ax_bw .plot (
144+ threads ,
145+ bandwidth ,
146+ marker = "o" ,
147+ linestyle = "-" ,
148+ linewidth = 2 ,
149+ )
150+ color = bw_line .get_color ()
151+ (lat_line ,) = ax_lat .plot (
152+ threads ,
153+ latency ,
154+ marker = "x" ,
155+ linestyle = "--" ,
156+ linewidth = 2 ,
157+ color = color ,
158+ )
159+
160+ bw_handles .append (bw_line )
161+ lat_handles .append (lat_line )
162+ legend_labels .append (f"{ access_type } BW" )
163+ legend_labels .append (f"{ access_type } Lat" )
164+
165+ ax_bw .set_title (f"{ title_prefix } : Threads vs Bandwidth & Latency" )
166+ ax_bw .set_xlabel ("Number of Threads" )
167+ ax_bw .set_ylabel ("Bandwidth (GiB/s)" , color = "tab:blue" )
168+ ax_lat .set_ylabel ("Latency (ns)" , color = "tab:red" )
169+ ax_lat .set_ylim (0 , 2500 )
170+
171+ ax_bw .tick_params (axis = "y" , labelcolor = "tab:blue" )
172+ ax_lat .tick_params (axis = "y" , labelcolor = "tab:red" )
173+ ax_bw .grid (True )
174+
175+ # Legend
176+ if bw_handles and lat_handles :
177+ if single_access_type :
178+ ax_bw .legend ([bw_handles [0 ], lat_handles [0 ]], legend_labels [:2 ], loc = "best" )
179+ else :
180+ handles = []
181+ for i in range (len (bw_handles )):
182+ handles .append (bw_handles [i ])
183+ handles .append (lat_handles [i ])
184+ ax_bw .legend (handles , legend_labels , loc = "best" )
185+
186+ fig .tight_layout ()
187+ fig .savefig (output_file )
188+ plt .close (fig )
92189
93190def plot_bw_latency (base_dir ):
94191 file_path = base_dir + "/parsed_result_logs.csv"
@@ -105,12 +202,14 @@ def plot_bw_latency(base_dir):
105202 "bandwidth_vs_latency" : os .path .join (output_dir , "load_bandwidth_vs_latency_plot.pdf" ),
106203 "threads_vs_bandwidth" : os .path .join (output_dir , "load_threads_vs_bandwidth_plot.pdf" ),
107204 "threads_vs_latency" : os .path .join (output_dir , "load_threads_vs_latency_plot.pdf" ),
205+ "threads_vs_bw_latency" : os .path .join (output_dir , "load_threads_vs_bw_latency_plot.pdf" ),
108206 }
109207
110208 store_output_files = {
111209 "bandwidth_vs_latency" : os .path .join (output_dir , "store_bandwidth_vs_latency_plot.pdf" ),
112210 "threads_vs_bandwidth" : os .path .join (output_dir , "store_threads_vs_bandwidth_plot.pdf" ),
113211 "threads_vs_latency" : os .path .join (output_dir , "store_threads_vs_latency_plot.pdf" ),
212+ "threads_vs_bw_latency" : os .path .join (output_dir , "store_threads_vs_bw_latency_plot.pdf" ),
114213 }
115214
116215 if load_data .empty :
@@ -119,10 +218,12 @@ def plot_bw_latency(base_dir):
119218 plot_bandwidth_vs_latency_and_save (load_data , load_output_files ["bandwidth_vs_latency" ], "LOAD" )
120219 plot_threads_vs_bandwidth_and_save (load_data , load_output_files ["threads_vs_bandwidth" ], "LOAD" )
121220 plot_threads_vs_latency_and_save (load_data , load_output_files ["threads_vs_latency" ], "LOAD" )
221+ plot_threads_vs_bw_latency_and_save (load_data , load_output_files ["threads_vs_bw_latency" ], "LOAD" )
122222
123223 if store_data .empty :
124224 logger .info ("No STORE data found." )
125225 else :
126226 plot_bandwidth_vs_latency_and_save (store_data , store_output_files ["bandwidth_vs_latency" ], "STORE" )
127227 plot_threads_vs_bandwidth_and_save (store_data , store_output_files ["threads_vs_bandwidth" ], "STORE" )
128228 plot_threads_vs_latency_and_save (store_data , store_output_files ["threads_vs_latency" ], "STORE" )
229+ plot_threads_vs_bw_latency_and_save (store_data , store_output_files ["threads_vs_bw_latency" ], "STORE" )
0 commit comments