Skip to content

Commit 97d4e26

Browse files
committed
Adda compare disk/mem mode for compressed Blosc2
1 parent 7b3288c commit 97d4e26

File tree

1 file changed

+142
-59
lines changed

1 file changed

+142
-59
lines changed

bench/ndarray/roofline-plot.py

Lines changed: 142 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
machine = "AMD-7800X3D"
2121
# False -> on-disk benchmark, True -> in-memory benchmark
2222
mem_mode = False
23+
# Whether we want to compare just compressed Blosc2 in-memory vs on-disk
24+
compare_disk_mem = False
2325

2426
# ---------------------------------------------------------------------
2527
# Benchmark dictionaries (raw string form, as produced by driver script)
@@ -273,72 +275,153 @@
273275
# ---------------------------------------------------------------------
274276
# Plotting
275277
# ---------------------------------------------------------------------
276-
fig, ax = plt.subplots(figsize=(10, 6))
277278

278-
styles = {
279-
'numpy/numexpr': {'color': 'blue', 'marker': 'o', 'label': 'NumPy/NumExpr'},
280-
'blosc2': {'color': 'red', 'marker': 's', 'label': 'Blosc2 (compressed)'},
281-
'blosc2-nocomp': {'color': 'green', 'marker': '^', 'label': 'Blosc2 (uncompressed)'},
282-
}
279+
if compare_disk_mem:
280+
# Comparison plot: Blosc2 disk vs memory for both machines
281+
fig, ax = plt.subplots(figsize=(10, 6))
282+
283+
comp_styles = {
284+
'AMD-7800X3D-mem': {'color': 'blue', 'marker': 'v', 'label': 'AMD 7800X3D (in-memory)', 'offset': 0.87},
285+
'AMD-7800X3D-disk': {'color': 'red', 'marker': '^', 'label': 'AMD 7800X3D (on-disk)', 'offset': 0.87},
286+
'Apple-M4-Pro-mem': {'color': 'blue', 'marker': 's', 'label': 'Apple M4 Pro (in-memory)', 'offset': 1.15},
287+
'Apple-M4-Pro-disk': {'color': 'red', 'marker': 'o', 'label': 'Apple M4 Pro (on-disk)', 'offset': 1.15},
288+
}
289+
290+
# Plot Blosc2 results for both machines and both modes (mem first, then disk)
291+
for machine_name in ['AMD-7800X3D', 'Apple-M4-Pro']:
292+
for mode_name in ['mem', 'disk']:
293+
key = f'{machine_name}-{mode_name}'
294+
data_str = BENCH_DATA[machine_name][mode_name]
295+
data = ast.literal_eval(data_str)
296+
297+
# Extract only Blosc2 (compressed) data
298+
if 'blosc2' in data:
299+
blosc2_data = data['blosc2']
300+
intensities = []
301+
gflops = []
283302

284-
# Plot each backend's results
285-
for backend, backend_results in results.items():
286-
intensities = []
287-
gflops = []
288-
labels = []
289-
for workload, metrics in backend_results.items():
290-
intensities.append(metrics['Intensity'])
291-
gflops.append(metrics['GFLOPS'])
292-
labels.append(workload)
303+
for workload, metrics in blosc2_data.items():
304+
intensities.append(metrics['Intensity'])
305+
gflops.append(metrics['GFLOPS'])
293306

294-
style = styles[backend]
295-
ax.loglog(
296-
intensities,
297-
gflops,
298-
marker=style['marker'],
299-
color=style['color'],
300-
label=style['label'],
301-
markersize=8,
302-
linestyle='',
303-
alpha=0.7,
304-
)
307+
style = comp_styles[key]
308+
# Apply horizontal offset to separate markers by machine
309+
offset_intensities = [i * style['offset'] for i in intensities]
305310

306-
# Build a single annotation per unique x (Intensity)
307-
intensity_map = {}
308-
for backend_results in results.values():
309-
for workload, metrics in backend_results.items():
311+
ax.loglog(
312+
offset_intensities,
313+
gflops,
314+
marker=style['marker'],
315+
color=style['color'],
316+
label=style['label'],
317+
markersize=8,
318+
linestyle='',
319+
alpha=0.7,
320+
)
321+
322+
# Add single set of workload labels (from Apple M4 Pro disk data)
323+
apple_disk = ast.literal_eval(BENCH_DATA['Apple-M4-Pro']['disk'])
324+
intensity_map_comp = {}
325+
for workload, metrics in apple_disk['blosc2'].items():
310326
intensity = metrics['Intensity']
311327
gflop = metrics['GFLOPS']
312-
if intensity not in intensity_map:
313-
intensity_map[intensity] = {'label': workload, 'gflops': []}
314-
intensity_map[intensity]['gflops'].append(gflop)
328+
if intensity not in intensity_map_comp:
329+
intensity_map_comp[intensity] = {'label': workload, 'min_gflops': gflop}
330+
else:
331+
intensity_map_comp[intensity]['min_gflops'] = min(intensity_map_comp[intensity]['min_gflops'], gflop)
332+
333+
ax.set_xlim(0.1, 5e4)
334+
ax.set_ylim(0.1, 1000.0)
335+
336+
for intensity, info in sorted(intensity_map_comp.items()):
337+
safe_ypos = max(info['min_gflops'] * 0.3, 0.002)
338+
ax.annotate(
339+
info['label'],
340+
(intensity, safe_ypos),
341+
ha='center',
342+
va='top',
343+
fontsize=10,
344+
alpha=0.9,
345+
)
346+
347+
ax.set_xlabel('Arithmetic Intensity (FLOPs/element)', fontsize=12)
348+
ax.set_ylabel('Performance (GFLOPS/sec)', fontsize=12)
349+
ax.set_title('Roofline Comparison: Compressed Blosc2 Memory vs Disk', fontsize=14, fontweight='bold')
350+
ax.legend(loc='upper left')
351+
ax.grid(False)
352+
353+
plt.tight_layout()
354+
plt.savefig('roofline_blosc2_comparison.png', dpi=300, bbox_inches='tight')
355+
plt.show()
356+
357+
else:
358+
# Original single-mode plot
359+
fig, ax = plt.subplots(figsize=(10, 6))
360+
361+
styles = {
362+
'numpy/numexpr': {'color': 'blue', 'marker': 'o', 'label': 'NumPy/NumExpr'},
363+
'blosc2': {'color': 'red', 'marker': 's', 'label': 'Blosc2 (compressed)'},
364+
'blosc2-nocomp': {'color': 'green', 'marker': '^', 'label': 'Blosc2 (uncompressed)'},
365+
}
366+
367+
# Plot each backend's results
368+
for backend, backend_results in results.items():
369+
intensities = []
370+
gflops = []
371+
labels = []
372+
for workload, metrics in backend_results.items():
373+
intensities.append(metrics['Intensity'])
374+
gflops.append(metrics['GFLOPS'])
375+
labels.append(workload)
376+
377+
style = styles[backend]
378+
ax.loglog(
379+
intensities,
380+
gflops,
381+
marker=style['marker'],
382+
color=style['color'],
383+
label=style['label'],
384+
markersize=8,
385+
linestyle='',
386+
alpha=0.7,
387+
)
388+
389+
# Build a single annotation per unique x (Intensity)
390+
intensity_map = {}
391+
for backend_results in results.values():
392+
for workload, metrics in backend_results.items():
393+
intensity = metrics['Intensity']
394+
gflop = metrics['GFLOPS']
395+
if intensity not in intensity_map:
396+
intensity_map[intensity] = {'label': workload, 'gflops': []}
397+
intensity_map[intensity]['gflops'].append(gflop)
315398

316-
# Axes limits
317-
ax.set_xlim(0.1, 5e4)
318-
ymin = 0.1 if mem_mode else 0.001
319-
ax.set_ylim(ymin, 2000.0)
399+
# Axes limits
400+
ax.set_xlim(0.1, 5e4)
401+
ymin = 0.1 if mem_mode else 0.001
402+
ax.set_ylim(ymin, 2000.0)
320403

321-
# Annotate once per intensity, centered under the cluster of points
322-
for intensity, info in sorted(intensity_map.items()):
323-
raw_ypos = min(info['gflops']) * 0.6
324-
ymin_curr, ymax_curr = ax.get_ylim()
325-
safe_ypos = max(raw_ypos, ymin_curr * 1.5 if ymin_curr > 0 else raw_ypos)
326-
ax.annotate(
327-
info['label'],
328-
(intensity, safe_ypos),
329-
ha='center',
330-
va='top',
331-
fontsize=10,
332-
alpha=0.9,
333-
)
404+
# Annotate once per intensity, centered under the cluster of points
405+
for intensity, info in sorted(intensity_map.items()):
406+
raw_ypos = min(info['gflops']) * 0.6
407+
ymin_curr, ymax_curr = ax.get_ylim()
408+
safe_ypos = max(raw_ypos, ymin_curr * 1.5 if ymin_curr > 0 else raw_ypos)
409+
ax.annotate(
410+
info['label'],
411+
(intensity, safe_ypos),
412+
ha='center',
413+
va='top',
414+
fontsize=10,
415+
alpha=0.9,
416+
)
334417

335-
ax.set_xlabel('Arithmetic Intensity (FLOPs/element)', fontsize=12)
336-
ax.set_ylabel('Performance (GFLOPS/sec)', fontsize=12)
337-
machine2 = machine.replace("-", " ")
338-
ax.set_title(f'Roofline Analysis: {machine2} ({legend})', fontsize=14, fontweight='bold')
339-
ax.legend(loc='upper left')
340-
ax.grid(False)
418+
ax.set_xlabel('Arithmetic Intensity (FLOPs/element)', fontsize=12)
419+
ax.set_ylabel('Performance (GFLOPS/sec)', fontsize=12)
420+
machine2 = machine.replace("-", " ")
421+
ax.set_title(f'Roofline Analysis: {machine2} ({legend})', fontsize=14, fontweight='bold')
422+
ax.legend(loc='upper left')
423+
ax.grid(False)
341424

342-
plt.tight_layout()
343-
plt.savefig(f'roofline_plot-{machine}-{legend}.png', dpi=300, bbox_inches='tight')
344-
plt.show()
425+
plt.tight_layout()
426+
plt.savefig(f'roofline_plot-{machine}-{legend}.png', dpi=300, bbox_inches='tight')
427+
plt.show()

0 commit comments

Comments
 (0)