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%
1a8bb6aMake the cross-language benchmark measure the languagesJeremy Magland 10% Because this runs the chapter's own script, whatever that script does badly
11% it does badly here too, which is a virtue for comparing MATLAB against numbl
12% and a hazard for comparing MATLAB against the Python and Julia ports. The
13% shape the script uses, a scalar double loop for the kernel matrix, happens to
14% be the fastest of the three shapes available in both MATLAB and numbl, so
15% nothing is being given away; if that ever stops being true, the honest fix is
16% to change the chapter, not to keep a faster copy here.
17%
6292f12A benchmark chapter, and offline benchmarks to compare it againstJeremy Magland 18% matlab -batch "run('bench/matlab/bench_pacman.m')"
19%
20% from the repository root writes bench-pacman-matlab.json into the
21% repository root (run() changes the working directory while it executes, so
22% "the current directory" would be a moving target). Load that file from the
23% benchmark chapter's "load offline results" button; because it ran on the
24% same machine as your browser, the timings share a clock and can share an
25% axis.
27here = fileparts(mfilename('fullpath'));
28root = fileparts(fileparts(here));
29outfile = fullfile(root, 'bench-pacman-matlab.json');
31% the deep basis ladders are legitimately rank deficient at the 1e-12 level;
32% Chapter 9 discusses why, and the warning would repeat once per solve
33warning('off', 'MATLAB:rankDeficientMatrix');
35kind = 'both';
36% ladders: zeros skip a method (rows: SW+SOR, basis, panels, Chebyshev)
37nsm = [0, 0, 0, 0, 0, 0;
38 4, 8, 16, 32, 48, 0;
39 4, 8, 12, 16, 20, 24;
40 0, 0, 0, 0, 0, 0];
42work = tempname;
43mkdir(work);
44libdir = fullfile(root, 'src', 'matlab');
45libfiles = dir(fullfile(libdir, '*.m'));
46for k = 1:numel(libfiles)
47 copyfile(fullfile(libdir, libfiles(k).name), work);
48end
49driver = fileread(fullfile(root, 'src', 'chapters', 'ch11', 'driver.m'));
50script = fileread(fullfile(root, 'src', 'chapters', 'ch11', 'pacman.m'));
51fid = fopen(fullfile(work, 'main.m'), 'w');
52fwrite(fid, sprintf('%s\n%s', driver, script));
53fclose(fid);
55params = struct('kind', kind, 'mode', 'sweep', 'nsm', nsm);
56fid = fopen(fullfile(work, 'params.json'), 'w');
57fwrite(fid, jsonencode(params));
58fclose(fid);
60old = cd(work);
61cleanup = onCleanup(@() cd(old));
62run('main.m');
63res = jsondecode(fileread('out.json'));
64cd(old);
66% out.json holds one row per method; keep the two that actually ran
67slots = {'fd2', 'mps', 'bie', 'spectral'};
68keep = [2, 3];
69methods = cell(1, numel(keep));
70for q = 1:numel(keep)
71 k = keep(q);
72 ns = pick_row(res.NS, k);
73 ok = isfinite(ns) & ns > 0;
74 m = struct();
75 m.name = res.names{k};
76 m.slot = slots{k};
77 m.ns = ns(ok);
78 m.E = pick_row(res.E, k);
79 m.E = m.E(ok);
80 m.T = pick_row(res.T, k);
81 m.T = m.T(ok);
82 methods{q} = m;
83end
85out = struct();
86out.schema = 'laplace-dirichlet-bench-1';
1a8bb6aMake the cross-language benchmark measure the languagesJeremy Magland 87out.label = sprintf('MATLAB %s, %d threads', version('-release'), maxNumCompThreads);
6292f12A benchmark chapter, and offline benchmarks to compare it againstJeremy Magland 88out.kind = kind;
89out.date = char(datetime('now', 'Format', 'yyyy-MM-dd'));
90out.methods = methods;
92fid = fopen(outfile, 'w');
93fwrite(fid, jsonencode(out));
94fclose(fid);
95fprintf('wrote %s\n', outfile);
97function r = pick_row(M, k)
98% jsondecode gives a matrix when the rows are rectangular and a cell of
99% columns when they are not; accept both.
100if iscell(M)
101 r = M{k}(:)';
102else
103 r = M(k, :);
104end
105end