6292f12A benchmark chapter, and offline benchmarks to compare it againstJeremy Magland 1% Offline benchmark of the Pac-Man problem in real MATLAB.
2%
3% Runs the tutorial's own MATLAB layer, unchanged: the chapter driver and the
4% editable script are concatenated into main.m exactly as the page does, and
5% executed here instead of in numbl. Only the two best methods from the
6% in-browser benchmark are swept (the harmonic basis and the graded-panel
7% double layer), with a deeper panel ladder than the page uses, since a native
8% LAPACK has no trouble with the larger dense systems.
9%
10% matlab -batch "run('bench/matlab/bench_pacman.m')"
11%
12% from the repository root writes bench-pacman-matlab.json into the
13% repository root (run() changes the working directory while it executes, so
14% "the current directory" would be a moving target). Load that file from the
15% benchmark chapter's "load offline results" button; because it ran on the
16% same machine as your browser, the timings share a clock and can share an
17% axis.
19here = fileparts(mfilename('fullpath'));
20root = fileparts(fileparts(here));
21outfile = fullfile(root, 'bench-pacman-matlab.json');
23% the deep basis ladders are legitimately rank deficient at the 1e-12 level;
24% Chapter 9 discusses why, and the warning would repeat once per solve
25warning('off', 'MATLAB:rankDeficientMatrix');
27kind = 'both';
28% ladders: zeros skip a method (rows: SW+SOR, basis, panels, Chebyshev)
29nsm = [0, 0, 0, 0, 0, 0;
30 4, 8, 16, 32, 48, 0;
31 4, 8, 12, 16, 20, 24;
32 0, 0, 0, 0, 0, 0];
34work = tempname;
35mkdir(work);
36libdir = fullfile(root, 'src', 'matlab');
37libfiles = dir(fullfile(libdir, '*.m'));
38for k = 1:numel(libfiles)
39 copyfile(fullfile(libdir, libfiles(k).name), work);
40end
41driver = fileread(fullfile(root, 'src', 'chapters', 'ch11', 'driver.m'));
42script = fileread(fullfile(root, 'src', 'chapters', 'ch11', 'pacman.m'));
43fid = fopen(fullfile(work, 'main.m'), 'w');
44fwrite(fid, sprintf('%s\n%s', driver, script));
45fclose(fid);
47params = struct('kind', kind, 'mode', 'sweep', 'nsm', nsm);
48fid = fopen(fullfile(work, 'params.json'), 'w');
49fwrite(fid, jsonencode(params));
50fclose(fid);
52old = cd(work);
53cleanup = onCleanup(@() cd(old));
54run('main.m');
55res = jsondecode(fileread('out.json'));
56cd(old);
58% out.json holds one row per method; keep the two that actually ran
59slots = {'fd2', 'mps', 'bie', 'spectral'};
60keep = [2, 3];
61methods = cell(1, numel(keep));
62for q = 1:numel(keep)
63 k = keep(q);
64 ns = pick_row(res.NS, k);
65 ok = isfinite(ns) & ns > 0;
66 m = struct();
67 m.name = res.names{k};
68 m.slot = slots{k};
69 m.ns = ns(ok);
70 m.E = pick_row(res.E, k);
71 m.E = m.E(ok);
72 m.T = pick_row(res.T, k);
73 m.T = m.T(ok);
74 methods{q} = m;
75end
77out = struct();
78out.schema = 'laplace-dirichlet-bench-1';
79out.label = ['MATLAB ' version('-release')];
80out.kind = kind;
81out.date = char(datetime('now', 'Format', 'yyyy-MM-dd'));
82out.methods = methods;
84fid = fopen(outfile, 'w');
85fwrite(fid, jsonencode(out));
86fclose(fid);
87fprintf('wrote %s\n', outfile);
89function r = pick_row(M, k)
90% jsondecode gives a matrix when the rows are rectangular and a cell of
91% columns when they are not; accept both.
92if iscell(M)
93 r = M{k}(:)';
94else
95 r = M(k, :);
96end
97end