lib/chant/src/profiling/versus/runner.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const bench = @import("bench");
  3 const chant = @import("chant");
  4 const choir = @import("choir");
  5 const sys = @import("sys");
  6 
  7 const compiler = @import("compiler.zig");
  8 const event = @import("event.zig");
  9 const kernel_mod = @import("kernel.zig");
 10 const measure = @import("measure.zig");
 11 const options_mod = @import("options.zig");
 12 const row = @import("row.zig");
 13 const timer_mod = @import("timer.zig");
 14 
 15 const jsonl = choir.versus.jsonl;
 16 const oracle = choir.versus.oracle;
 17 const workload_mod = choir.versus.workload;
 18 
 19 const Allocator = std.mem.Allocator;
 20 const Workload = workload_mod.Workload;
 21 
 22 pub fn run(arena: Allocator, gpa: Allocator, environ: std.process.Environ, args: []const []const u8) !u8 {
 23     var stdout_buffer: [16384]u8 = undefined;
 24     var stdout = sys.stdio.stdout().writer(sys.stdio.debugIo(), &stdout_buffer);
 25     defer stdout.interface.flush() catch {};
 26     const out = &stdout.interface;
 27 
 28     const options = options_mod.parse(args) orelse {
 29         try bench.pretty.write(out, .{ .text = options_mod.usage_text }, .{});
 30         return 0;
 31     };
 32 
 33     try event.writeRunStart(out, options);
 34     try jsonl.writeMeta(out, "harness", "x86_64-linux", "chant frontend lane over the shared versus corpus");
 35 
 36     sys.fs.createDirPath(options.workdir) catch {};
 37 
 38     for (workload_mod.battery) |workload| {
 39         if (options.workload) |only| {
 40             if (!std.mem.eql(u8, workload.name, only)) continue;
 41         }
 42         try runWorkload(arena, gpa, out, environ, workload, options);
 43     }
 44     try event.writeRunEnd(out, options);
 45     return 0;
 46 }
 47 
 48 fn runWorkload(
 49     arena: Allocator,
 50     gpa: Allocator,
 51     out: *std.Io.Writer,
 52     environ: std.process.Environ,
 53     workload: Workload,
 54     options: options_mod.Options,
 55 ) !void {
 56     var ctx = try choir.Context.init(arena, choir.Context.Limits.standard);
 57     defer ctx.deinit(arena);
 58     try choir.dialects.registerAllDialects(&ctx);
 59 
 60     var timer = timer_mod.start();
 61     var compile_diagnostic: chant.Diagnostic = .{};
 62     const unit = compiler.compileCorpus(gpa, arena, &ctx, environ, workload, options, &compile_diagnostic) catch |err| {
 63         const reason = if (compile_diagnostic.message.len != 0)
 64             try std.fmt.allocPrint(arena, "{s}: {s}", .{ @errorName(err), compile_diagnostic.message })
 65         else
 66             @errorName(err);
 67         try row.skipped(out, workload, reason);
 68         return;
 69     };
 70     const symbol = workload.kind.symbol();
 71     var lowered = false;
 72     for (unit.lowered.items) |name| {
 73         if (std.mem.eql(u8, name, symbol)) lowered = true;
 74     }
 75     if (!lowered) {
 76         var reason: []const u8 = "kernel not lowered";
 77         for (unit.skipped.items) |skipped| {
 78             if (std.mem.eql(u8, skipped.name, symbol)) reason = @errorName(skipped.reason);
 79         }
 80         try row.skipped(out, workload, reason);
 81         return;
 82     }
 83 
 84     {
 85         var pass_manager = choir.passes.PassManager.init(arena);
 86         defer pass_manager.deinit();
 87         choir.passes.addDefaultOptimizationPipeline(&pass_manager) catch |err| {
 88             try row.skipped(out, workload, @errorName(err));
 89             return;
 90         };
 91         const pass_result = pass_manager.run(unit.module.op, &ctx);
 92         if (pass_result != .success) {
 93             try row.skipped(out, workload, "pipeline failed");
 94             return;
 95         }
 96     }
 97 
 98     var backend = try choir.backends.x86_64.backend.Backend.init(arena, &ctx, .standard);
 99     defer backend.deinit();
100     const compiled = backend.compile(unit.module.op) catch |err| {
101         try row.skipped(out, workload, @errorName(err));
102         return;
103     };
104     const compile_ns = timer_mod.read(&timer);
105 
106     try jsonl.writeRow(out, .{
107         .system = row.system,
108         .workload = workload.name,
109         .metric = .compile_ns,
110         .samples = 1,
111         .median_ns = compile_ns,
112         .p10_ns = compile_ns,
113         .p90_ns = compile_ns,
114         .flops = workload.flops(),
115         .moved_bytes = workload.movedBytes(),
116     });
117 
118     const kernel = (try kernel_mod.open(&backend.runtime, compiled, workload.kind)) orelse {
119         try row.skipped(out, workload, "kernel symbol missing after compile");
120         return;
121     };
122 
123     var buffers = try oracle.Buffers.alloc(arena, workload);
124     try measure.run(arena, out, workload, &buffers, kernel, options);
125 }