44 samples = [NATIVE_TIMES_MS, EIGEN_TIMES_MS, VULKAN_TIMES_MS]
45 means = np.array([values.mean() for values in samples])
46 fps = FRAME_COUNT / (means / 1000.0)
47
48 eigen_difference = (means[1] - means[0]) / means[0] * 100.0
49 vulkan_reduction = (means[0] - means[2]) / means[0] * 100.0
50 vulkan_speedup = means[0] / means[2]
51
52 figure = plt.figure(figsize=(12, 6.75), dpi=100, facecolor=BACKGROUND_COLOR)
53 axis = figure.add_axes((0.14, 0.24, 0.77, 0.46), facecolor=PANEL_COLOR)
54
55 figure.text(
56 0.07,
57 0.91,
58 f"Vulkan renders the heavy-sphere OBJ {vulkan_speedup:.1f}× faster",
59 color=TEXT_COLOR,
60 fontsize=28,
61 fontweight="bold",
62 )
63 figure.text(
64 0.07,
65 0.845,
66 "32,514 indexed vertices • 65,024 triangles • 600 frames • 5 runs per backend",
67 color=MUTED_TEXT_COLOR,
68 fontsize=15,
69 )
70
71 y_positions = [2, 1, 0]
72 axis.barh(
73 y_positions,
74 means,
75 height=0.48,
76 color=[NATIVE_COLOR, EIGEN_COLOR, VULKAN_COLOR],
77 edgecolor="none",
78 zorder=2,
79 )
80
81 point_offsets = np.linspace(-0.14, 0.14, len(NATIVE_TIMES_MS))
82 for values, y_position, point_color in zip(
83 samples, y_positions, POINT_COLORS, strict=True
84 ):
85 axis.scatter(
86 values,
87 y_position + point_offsets,
88 s=42,
89 color=point_color,
90 edgecolor=BACKGROUND_COLOR,
91 linewidth=1.2,
92 zorder=3,
93 )
94
95 for mean, y_position in zip(means, y_positions, strict=True):
96 add_bar_label(axis, float(mean), y_position)
97
98 axis.set_xlim(0, 3700)
99 axis.set_ylim(-0.55, 2.55)
100 axis.set_yticks(y_positions, ["Native CPU", "Eigen CPU", "Vulkan GPU"])
101 axis.set_xlabel(
102 "Average time for 600 frames (lower is better)",
103 color=MUTED_TEXT_COLOR,
104 fontsize=13,
105 labelpad=12,
106 )
107 axis.tick_params(axis="x", colors=MUTED_TEXT_COLOR, labelsize=11)
108 axis.tick_params(axis="y", colors=TEXT_COLOR, labelsize=16, length=0, pad=12)
109 axis.xaxis.grid(True, color=GRID_COLOR, linewidth=1, alpha=0.65)
110 axis.set_axisbelow(True)
111 for spine in axis.spines.values():
112 spine.set_visible(False)
113
114 figure.text(
115 0.07,
116 0.11,
117 f"Native {fps[0]:,.0f} FPS • Eigen {fps[1]:,.0f} FPS • Vulkan {fps[2]:,.0f} FPS",
118 color=TEXT_COLOR,
119 fontsize=14,
120 fontweight="bold",
121 )
122 figure.text(
123 0.07,
124 0.055,
125 f"Eigen vs native: {eigen_difference:+.1f}% time • Vulkan vs native: {vulkan_reduction:.1f}% less time",
126 color=MUTED_TEXT_COLOR,
127 fontsize=13,
128 )
129 figure.text(
130 0.93,
131 0.055,
132 "RTX 2070",
133 color=VULKAN_COLOR,
134 fontsize=13,
135 fontweight="bold",
136 ha="right",
137 )
138
139 output_path = Path(__file__).with_name("benchmark_obj_backends.png")
140 figure.savefig(output_path, dpi=160, facecolor=figure.get_facecolor())
141 plt.close(figure)
142
143 print(f"Native mean: {means[0]:.3f} ms ({fps[0]:.1f} FPS)")
144 print(f"Eigen mean: {means[1]:.3f} ms ({fps[1]:.1f} FPS)")
145 print(f"Vulkan mean: {means[2]:.3f} ms ({fps[2]:.1f} FPS)")
146 print(f"Eigen vs native: {eigen_difference:+.3f}% time")
147 print(
148 f"Vulkan vs native: {vulkan_reduction:.3f}% less time "
149 f"({vulkan_speedup:.3f}x faster)"
150 )
151 print(output_path)
152
153