@@ -70,6 +70,105 @@ fn benchmark_sin_cos_system(comptime size: usize) type {
7070 };
7171}
7272
73+ // Fill a length-`size` array with distinct positive values (kept away from zero
74+ // so reductions/normalize stay well-conditioned).
75+ fn ramp (comptime size : usize ) [size ]f32 {
76+ var val : [size ]f32 = undefined ;
77+ for (0.. size ) | k | val [k ] = @as (f32 , @floatFromInt (k % 251 )) * 0.03 + 1.0 ;
78+ return val ;
79+ }
80+
81+ // `sin_cos` on a plain array: processed in native-width SIMD chunks (simd.zig).
82+ fn bench_sin_cos_array (comptime size : usize ) type {
83+ return struct {
84+ angles : [size ]f32 ,
85+ fn init () @This () {
86+ return .{ .angles = ramp (size ) };
87+ }
88+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
89+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .sin_cos , .{self .angles }));
90+ }
91+ };
92+ }
93+
94+ // The remaining factories each come in an `_array` (chunked) and a `_vector`
95+ // (single wide @Vector op) flavor over the SAME data, so a run shows the
96+ // chunked path's cost against the wide-vector path it replaces for arrays.
97+
98+ fn bench_norm_array (comptime size : usize ) type {
99+ return struct {
100+ data : [size ]f32 ,
101+ fn init () @This () {
102+ return .{ .data = ramp (size ) };
103+ }
104+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
105+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .norm_adv , .{ self .data , 32 }));
106+ }
107+ };
108+ }
109+
110+ fn bench_norm_vector (comptime size : usize ) type {
111+ return struct {
112+ data : @Vector (size , f32 ),
113+ fn init () @This () {
114+ return .{ .data = ramp (size ) };
115+ }
116+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
117+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .norm_adv , .{ self .data , 32 }));
118+ }
119+ };
120+ }
121+
122+ fn bench_dot_array (comptime size : usize ) type {
123+ return struct {
124+ a : [size ]f32 ,
125+ b : [size ]f32 ,
126+ fn init () @This () {
127+ return .{ .a = ramp (size ), .b = ramp (size ) };
128+ }
129+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
130+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .dot , .{ self .a , self .b }));
131+ }
132+ };
133+ }
134+
135+ fn bench_dot_vector (comptime size : usize ) type {
136+ return struct {
137+ a : @Vector (size , f32 ),
138+ b : @Vector (size , f32 ),
139+ fn init () @This () {
140+ return .{ .a = ramp (size ), .b = ramp (size ) };
141+ }
142+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
143+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .dot , .{ self .a , self .b }));
144+ }
145+ };
146+ }
147+
148+ fn bench_normalize_array (comptime size : usize ) type {
149+ return struct {
150+ data : [size ]f32 ,
151+ fn init () @This () {
152+ return .{ .data = ramp (size ) };
153+ }
154+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
155+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .normalize , .{self .data }));
156+ }
157+ };
158+ }
159+
160+ fn bench_normalize_vector (comptime size : usize ) type {
161+ return struct {
162+ data : @Vector (size , f32 ),
163+ fn init () @This () {
164+ return .{ .data = ramp (size ) };
165+ }
166+ pub fn run (self : * @This (), _ : std .mem .Allocator ) void {
167+ std .mem .doNotOptimizeAway (@call (.never_inline , zml .vec .normalize , .{self .data }));
168+ }
169+ };
170+ }
171+
73172pub fn main () ! void {
74173 const io = std .Io .Threaded .global_single_threaded .io ();
75174 const stdout : std.Io.File = .stdout ();
@@ -89,6 +188,29 @@ pub fn main() !void {
89188 try bench .addParam ("Sin/Cos vectorized" , & bench_sin_cos_fused (256 ).init (), .{
90189 .iterations = 256 ,
91190 });
191+ try bench .addParam ("Sin/Cos array (chunked)" , & bench_sin_cos_array (256 ).init (), .{
192+ .iterations = 256 ,
193+ });
194+
195+ // Chunked array path vs single wide-@Vector op, at the motivating length 245.
196+ try bench .addParam ("norm [245] array (chunked)" , & bench_norm_array (245 ).init (), .{
197+ .iterations = 4096 ,
198+ });
199+ try bench .addParam ("norm @Vector(245)" , & bench_norm_vector (245 ).init (), .{
200+ .iterations = 4096 ,
201+ });
202+ try bench .addParam ("dot [245] array (chunked)" , & bench_dot_array (245 ).init (), .{
203+ .iterations = 4096 ,
204+ });
205+ try bench .addParam ("dot @Vector(245)" , & bench_dot_vector (245 ).init (), .{
206+ .iterations = 4096 ,
207+ });
208+ try bench .addParam ("normalize [245] array (chunked)" , & bench_normalize_array (245 ).init (), .{
209+ .iterations = 4096 ,
210+ });
211+ try bench .addParam ("normalize @Vector(245)" , & bench_normalize_vector (245 ).init (), .{
212+ .iterations = 4096 ,
213+ });
92214
93215 try bench .run (io , stdout );
94216}
0 commit comments