"""GPU Utilization Paradox Chart""" import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.patches import Circle import numpy as np from src.utils.styling import ( get_theme, EXPORT_DPI, BUBBLE_ZONE, NORMAL_ZONE, WARNING_ZONE, GRAY_LIGHT, GRAY_DARK, GRAY_MEDIUM, BLACK, WHITE ) from src.utils.export import save_chart_tight def plot_gpu_utilization() -> str: plt.rcParams.update(get_theme()) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8)) # --------------------------------------------------------------------------- # LEFT PANEL: Horizontal bar comparison # --------------------------------------------------------------------------- categories = [ "Total AI Infrastructure Spend (2025)", "Effective GPU Utilization (~5%)", "Industry Target (~65%)", "Human Workforce Utilization (~85%)", ] # Normalize to percentages for visual comparison values = [100, 5, 65, 85] colors_bar = [GRAY_DARK, BUBBLE_ZONE, NORMAL_ZONE, WARNING_ZONE] y_pos = np.arange(len(categories)) bars = ax1.barh(y_pos, values, color=colors_bar, edgecolor="white", height=0.6) ax1.set_yticks(y_pos) ax1.set_yticklabels(categories, fontsize=11) ax1.set_xlabel("Relative Percentage (%)", fontsize=12) ax1.set_title("GPU Utilization Paradox", fontsize=16, fontweight="bold") ax1.set_xlim(0, 110) ax1.grid(True, alpha=0.3, axis="x") # Value labels on bars for bar, val in zip(bars, values): ax1.text( val + 1, bar.get_y() + bar.get_height() / 2, f"{val}%", va="center", fontsize=11, fontweight="bold", ) # --------------------------------------------------------------------------- # RIGHT PANEL: Donut chart # --------------------------------------------------------------------------- sizes = [5, 95] # Utilized vs Idle colors_donut = [BUBBLE_ZONE, GRAY_LIGHT] labels_donut = ["Utilized (5%)", "Idle (95%)"] wedges, texts, autotexts = ax2.pie( sizes, colors=colors_donut, startangle=90, textprops={"fontsize": 10}, autopct="", counterclock=False, ) # Inner circle for donut centre_circle = Circle((0, 0), 0.65, fc=WHITE) ax2.add_artist(centre_circle) # Center text ax2.text( 0, 0, "5%\nGPU\nUTIL", ha="center", va="center", fontsize=20, fontweight="bold", color=BUBBLE_ZONE, ) ax2.set_title("GPU Capacity Breakdown", fontsize=14, fontweight="bold") ax2.legend(wedges, labels_donut, loc="lower right", fontsize=10) # --------------------------------------------------------------------------- # FIGURE-LEVEL: Title, subtitle, callout, source # --------------------------------------------------------------------------- fig.suptitle( "The GPU Utilization Paradox", fontsize=22, fontweight="bold", y=0.98, ) fig.text( 0.5, 0.93, "\\$400B+ spent on AI infrastructure — ~5% average GPU utilization", ha="center", fontsize=13, color=GRAY_MEDIUM, ) # Bold callout fig.text( 0.5, 0.02, "\\$295B+ spent | ~5% utilized | ~\\$280B wasted capacity", ha="center", fontsize=14, fontweight="bold", bbox=dict( boxstyle="round,pad=0.5", facecolor=GRAY_LIGHT, edgecolor=BUBBLE_ZONE, linewidth=2, ), ) # Source note fig.text( 0.5, 0.07, "Enterprise GPU utilization estimates from industry surveys (2024-2025)", ha="center", fontsize=9, color=GRAY_MEDIUM, style="italic", ) path = save_chart_tight(fig, "08_gpu_utilization.png") plt.close(fig) return path def main(): path = plot_gpu_utilization() print(f"Chart saved: {path}") if __name__ == "__main__": main()