Compare commits
2
Commits
0.1.1
..
3a4783cfa1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a4783cfa1 | ||
|
|
80cdcd134e |
@@ -7,8 +7,6 @@ const UnitScale = Scales.UnitScale;
|
|||||||
const Dimensions = @import("Dimensions.zig");
|
const Dimensions = @import("Dimensions.zig");
|
||||||
const Dimension = Dimensions.Dimension;
|
const Dimension = Dimensions.Dimension;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// A dimensioned scalar value. `T` is the numeric type, `d` the dimension exponents, `s` the SI scales.
|
/// A dimensioned scalar value. `T` is the numeric type, `d` the dimension exponents, `s` the SI scales.
|
||||||
/// All dimension and unit tracking is resolved at comptime — zero runtime overhead.
|
/// All dimension and unit tracking is resolved at comptime — zero runtime overhead.
|
||||||
pub fn Scalar(comptime T: type, comptime d_opt: Dimensions.ArgOpts, comptime s_opt: Scales.ArgOpts) type {
|
pub fn Scalar(comptime T: type, comptime d_opt: Dimensions.ArgOpts, comptime s_opt: Scales.ArgOpts) type {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Element-wise subtraction. Dimensions must match; scales resolve to the finer of the two.
|
/// Element-wise subtraction. Dimensions must match; scales resolve to the finer of the two.
|
||||||
pub inline fn sub(self: Self, rhs: anytype) Vector(len, Scalar(
|
pub inline fn sub(self: Self, rhs: anytype) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
|
|||||||
+101
-8
@@ -11,14 +11,25 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
|
|
||||||
io = init.io;
|
io = init.io;
|
||||||
|
|
||||||
try bench_Scalar(&stdout_writer.interface);
|
try vectorSIMDvsNative(f64, &stdout_writer.interface);
|
||||||
try stdout_writer.flush();
|
try stdout_writer.flush();
|
||||||
try bench_vsNative(&stdout_writer.interface);
|
try vectorSIMDvsNative(f32, &stdout_writer.interface);
|
||||||
try stdout_writer.flush();
|
try stdout_writer.flush();
|
||||||
try bench_crossTypeVsNative(&stdout_writer.interface);
|
try vectorSIMDvsNative(i32, &stdout_writer.interface);
|
||||||
try stdout_writer.flush();
|
try stdout_writer.flush();
|
||||||
try bench_Vector(&stdout_writer.interface);
|
try vectorSIMDvsNative(i64, &stdout_writer.interface);
|
||||||
try stdout_writer.flush();
|
try stdout_writer.flush();
|
||||||
|
try vectorSIMDvsNative(i128, &stdout_writer.interface);
|
||||||
|
try stdout_writer.flush();
|
||||||
|
|
||||||
|
// try bench_Scalar(&stdout_writer.interface);
|
||||||
|
// try stdout_writer.flush();
|
||||||
|
// try bench_vsNative(&stdout_writer.interface);
|
||||||
|
// try stdout_writer.flush();
|
||||||
|
// try bench_crossTypeVsNative(&stdout_writer.interface);
|
||||||
|
// try stdout_writer.flush();
|
||||||
|
// try bench_Vector(&stdout_writer.interface);
|
||||||
|
// try stdout_writer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTime() Io.Timestamp {
|
fn getTime() Io.Timestamp {
|
||||||
@@ -161,7 +172,6 @@ fn bench_vsNative(writer: *std.Io.Writer) !void {
|
|||||||
const ITERS: usize = 100_000;
|
const ITERS: usize = 100_000;
|
||||||
const SAMPLES: usize = 5;
|
const SAMPLES: usize = 5;
|
||||||
|
|
||||||
// Helper to safely get a value of type T from a loop index
|
|
||||||
const getValT = struct {
|
const getValT = struct {
|
||||||
fn f(comptime TT: type, i: usize) TT {
|
fn f(comptime TT: type, i: usize) TT {
|
||||||
const v = (i % 100) + 1;
|
const v = (i % 100) + 1;
|
||||||
@@ -171,7 +181,8 @@ fn bench_vsNative(writer: *std.Io.Writer) !void {
|
|||||||
|
|
||||||
const Types = .{ i32, i64, i128, f32, f64 };
|
const Types = .{ i32, i64, i128, f32, f64 };
|
||||||
const TNames = .{ "i32", "i64", "i128", "f32", "f64" };
|
const TNames = .{ "i32", "i64", "i128", "f32", "f64" };
|
||||||
const Ops = .{ "add", "mul", "div" };
|
// Expanded Ops to match bench_Scalar
|
||||||
|
const Ops = .{ "add", "sub", "mul", "div", "abs", "eq", "gt" };
|
||||||
|
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\
|
\\
|
||||||
@@ -198,11 +209,24 @@ fn bench_vsNative(writer: *std.Io.Writer) !void {
|
|||||||
for (0..ITERS) |i| {
|
for (0..ITERS) |i| {
|
||||||
const a = getValT(T, i);
|
const a = getValT(T, i);
|
||||||
const b = getValT(T, 2);
|
const b = getValT(T, 2);
|
||||||
|
|
||||||
|
// Native logic branch
|
||||||
_ = if (comptime std.mem.eql(u8, op_name, "add"))
|
_ = if (comptime std.mem.eql(u8, op_name, "add"))
|
||||||
a + b
|
a + b
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "sub"))
|
||||||
|
a - b
|
||||||
else if (comptime std.mem.eql(u8, op_name, "mul"))
|
else if (comptime std.mem.eql(u8, op_name, "mul"))
|
||||||
a * b
|
a * b
|
||||||
else if (comptime @typeInfo(T) == .int) @divTrunc(a, b) else a / b;
|
else if (comptime std.mem.eql(u8, op_name, "div"))
|
||||||
|
if (comptime @typeInfo(T) == .int) @divTrunc(a, b) else a / b
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "abs"))
|
||||||
|
if (comptime @typeInfo(T) == .int) @abs(a) else @as(T, @abs(a))
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "eq"))
|
||||||
|
a == b
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "gt"))
|
||||||
|
a > b
|
||||||
|
else
|
||||||
|
unreachable;
|
||||||
}
|
}
|
||||||
const n_end = getTime();
|
const n_end = getTime();
|
||||||
native_total_ns += @as(f64, @floatFromInt(n_start.durationTo(n_end).toNanoseconds()));
|
native_total_ns += @as(f64, @floatFromInt(n_start.durationTo(n_end).toNanoseconds()));
|
||||||
@@ -213,12 +237,23 @@ fn bench_vsNative(writer: *std.Io.Writer) !void {
|
|||||||
const qa = M{ .value = getValT(T, i) };
|
const qa = M{ .value = getValT(T, i) };
|
||||||
const qb = if (comptime std.mem.eql(u8, op_name, "div")) S{ .value = getValT(T, 2) } else M{ .value = getValT(T, 2) };
|
const qb = if (comptime std.mem.eql(u8, op_name, "div")) S{ .value = getValT(T, 2) } else M{ .value = getValT(T, 2) };
|
||||||
|
|
||||||
|
// Scalar logic branch
|
||||||
_ = if (comptime std.mem.eql(u8, op_name, "add"))
|
_ = if (comptime std.mem.eql(u8, op_name, "add"))
|
||||||
qa.add(qb)
|
qa.add(qb)
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "sub"))
|
||||||
|
qa.sub(qb)
|
||||||
else if (comptime std.mem.eql(u8, op_name, "mul"))
|
else if (comptime std.mem.eql(u8, op_name, "mul"))
|
||||||
qa.mul(qb)
|
qa.mul(qb)
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "div"))
|
||||||
|
qa.div(qb)
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "abs"))
|
||||||
|
qa.abs()
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "eq"))
|
||||||
|
qa.eq(qb)
|
||||||
|
else if (comptime std.mem.eql(u8, op_name, "gt"))
|
||||||
|
qa.gt(qb)
|
||||||
else
|
else
|
||||||
qa.div(qb);
|
unreachable;
|
||||||
}
|
}
|
||||||
const q_end = getTime();
|
const q_end = getTime();
|
||||||
quantity_total_ns += @as(f64, @floatFromInt(q_start.durationTo(q_end).toNanoseconds()));
|
quantity_total_ns += @as(f64, @floatFromInt(q_start.durationTo(q_end).toNanoseconds()));
|
||||||
@@ -454,3 +489,61 @@ fn bench_Vector(writer: *std.Io.Writer) !void {
|
|||||||
}
|
}
|
||||||
try writer.print("└──────────────────┴──────┴─────────┴─────────┴─────────┘\n", .{});
|
try writer.print("└──────────────────┴──────┴─────────┴─────────┴─────────┘\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vectorSIMDvsNative(comptime T: type, writer: *std.Io.Writer) !void {
|
||||||
|
const iterations: u64 = 100_000;
|
||||||
|
const lens = [_]u32{ 1, 2, 3, 4, 5, 10, 100, 1_000, 10_000 };
|
||||||
|
|
||||||
|
try writer.print("\nSIMD Speedup Analysis: {s}\n", .{@typeName(T)});
|
||||||
|
try writer.print("┌────────────┬────────────┬────────────┬────────────┐\n", .{});
|
||||||
|
try writer.print("│ Vector Len │ Scalar (ns)│ Vector (ns)│ Speedup │\n", .{});
|
||||||
|
try writer.print("├────────────┼────────────┼────────────┼────────────┤\n", .{});
|
||||||
|
|
||||||
|
inline for (lens) |vector_len| {
|
||||||
|
// --- Scalar Test ---
|
||||||
|
var scalar_val: T = 10;
|
||||||
|
const start_scalar = getTime();
|
||||||
|
|
||||||
|
var i: u64 = 0;
|
||||||
|
while (i < iterations * vector_len) : (i += 1) {
|
||||||
|
if (comptime @typeInfo(T) == .int)
|
||||||
|
scalar_val = scalar_val +% 1
|
||||||
|
else
|
||||||
|
scalar_val = scalar_val + 1;
|
||||||
|
}
|
||||||
|
const scalar_time = start_scalar.durationTo(getTime()).toNanoseconds();
|
||||||
|
|
||||||
|
// --- Vector Test ---
|
||||||
|
var vector_val: @Vector(vector_len, T) = @splat(20);
|
||||||
|
const start_vector = getTime();
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
const increment: @Vector(vector_len, T) = @splat(1);
|
||||||
|
while (i < iterations) : (i += 1) {
|
||||||
|
if (comptime @typeInfo(T) == .int)
|
||||||
|
vector_val = vector_val +% increment
|
||||||
|
else
|
||||||
|
vector_val = vector_val + increment;
|
||||||
|
}
|
||||||
|
const vector_time = start_vector.durationTo(getTime()).toNanoseconds();
|
||||||
|
|
||||||
|
// --- Results ---
|
||||||
|
const s_float = @as(f64, @floatFromInt(scalar_time));
|
||||||
|
const v_float = @as(f64, @floatFromInt(vector_time));
|
||||||
|
|
||||||
|
// Speedup = ScalarTime / VectorTime.
|
||||||
|
// > 1.0 means SIMD is faster.
|
||||||
|
const speedup = if (vector_time > 0) s_float / v_float else 0;
|
||||||
|
|
||||||
|
try writer.print("│ {d:<10} │ {d:>10} │ {d:>10} │ {d:>9.2}x │\n", .{
|
||||||
|
vector_len,
|
||||||
|
scalar_time,
|
||||||
|
vector_time,
|
||||||
|
speedup,
|
||||||
|
});
|
||||||
|
|
||||||
|
std.mem.doNotOptimizeAway(scalar_val);
|
||||||
|
std.mem.doNotOptimizeAway(vector_val);
|
||||||
|
}
|
||||||
|
try writer.print("└────────────┴────────────┴────────────┴────────────┘\n", .{});
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -8,9 +8,9 @@ pub const Base = @import("Base.zig");
|
|||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("Scalar.zig");
|
_ = @import("Scalar.zig");
|
||||||
_ = @import("Vector.zig");
|
// _ = @import("Vector.zig");
|
||||||
_ = @import("Dimensions.zig");
|
// _ = @import("Dimensions.zig");
|
||||||
_ = @import("Scales.zig");
|
// _ = @import("Scales.zig");
|
||||||
_ = @import("Base.zig");
|
// _ = @import("Base.zig");
|
||||||
_ = @import("helper.zig");
|
// _ = @import("helper.zig");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user