Build1 distinct publisher3 min readPublished
A C benchmark on Apple Silicon puts a plain loop reorder 6.3x over naive and the best tile size 11% behind that, which suggests the first move on a hot loop is a stride check rather than a blocking rewrite.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The mechanism is stride, and it is legible in the index expression. In the naive `i,j,k` order the inner loop reads `B[k][j]`, walking down a column [6]. Each step skips a whole row, which at n=1024 with doubles is an 8 KB jump per multiply, so almost every access misses and the core sits waiting on memory at 2.6 GFLOP/s [7]. Swap the last two loops to `i,k,j` and the inner statement becomes `C[i][j] += a*B[k][j]` with `a = A[i][k]` hoisted out, so both remaining accesses march along contiguous rows at unit stride [8]. That is the shape the hardware prefetcher and the compiler's auto-vectorizer both handle well [9]. Same arithmetic, same `cc -O2`, 6.3x [2].
Put the rates on a clock. At n=1024 the work is 2*n^3, about 2.15 GFLOP [16]. Naive takes roughly 0.81 s, the reordered loop 0.13 s, and Accelerate about 5.2 ms [17]. So the free reorder recovers about 0.68 s of that 0.81, and everything else in the write-up is a fight over the remaining tenth of a second.
The tiled version loses for reasons the author names: this core has a large L2, the compiler already vectorizes the clean reordered inner loop into wide SIMD stores, and the blocked loop pays index arithmetic and loop overhead to relieve cache pressure that was not yet the binding constraint [10]. His best tile lands at 14.83 GFLOP/s, 11% under the reordered loop [3][18]. The sweep behaves exactly as theory says it should, throughput climbing with block size until three tiles at 3*T^2*8 bytes stop fitting in L2 [11]. For scale, a 256-wide tile of doubles puts that working set at 1.57 MB [19]. Every bar in the sweep still sits below 16.73 [11]. Tiling is the optimization with a diagram, which may be part of why it gets taught first.
For the "skip the blocking" reading to transfer, three things have to hold on your machine: an L2 large enough that a streaming loop is not already thrashing, a compiler that vectorizes the clean inner loop at -O2, and matrices near n=1024 rather than far above it. The author lists the same escape hatches from the other side, naming smaller-cache CPUs, much larger matrices, and multi-level registers/L1/L2 schemes as where blocking pays [12]. Note the third case: in real libraries tiling is a level inside a scheme, not a patch applied to a loop that already streams well.
One caveat the ratio hides, though the post is straight about it: part of the 24.5x is core count, because the BLAS figure carries multithreading across cores alongside SIMD, register blocking and per-CPU microkernels [13][4]. A single-threaded hand loop timed against a multithreaded library is not a per-core comparison, and nothing here tells you how much of the lead survives pinning Accelerate to one thread. The 155x is still the number that governs build-or-call, because closing it means reproducing all four of those techniques and not just the cache one. Loop-level work on this kernel tops out at 4.1% of Accelerate's throughput [20], which is why the author's own conclusion is to measure on your own hardware, call the library for real matmul, and spend hand-written effort where no library exists [15]. The benchmark was published on dev.to, syndicated from lkforge.com [21].
Ranked by verification strength, evidence, and original report placement.
The benchmark timed four matrix multiply implementations written in C, compiled the same way with cc -O2, on Apple Silicon (macOS) with the Accelerate BLAS backend, using the same matrices on the same machine and reporting GFLOP/s.
At n=1024, loop order alone was 6.3x faster than naive, moving from 2.64 to 16.73 GFLOP/s, with no blocking at all.
The author's best tiled version reached 14.83 GFLOP/s and never beat the plain reordered loop on this hardware.
BLAS reached about 410 GFLOP/s, which was 24.5x the author's best hand loop (16.73) and 155x the naive loop.
All four implementations produced the identical result, with matching checksums; only the speed differed.
The naive order is for i, for j, for k with C[i][j] += A[i][k]*B[k][j]; in the inner loop over k, A[i][k] walks along a contiguous row but B[k][j] walks down a column.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · September 2, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Eleven agent sessions on one machine settled CPU contention by writing to each other1 distinct publisher
build
Averaging five clips handed one rough take 20% of a TTS style vector1 distinct publisher
build
Shared memory in Java: the mmap is the easy half, the descriptor handoff is the work1 distinct publisher
build
Correlation gates pass a singular design matrix, and widen the dependency to quieten them further1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Reproducible recipe, single reading
The good part is unusually good for a blog benchmark: three kernels shipped as compilable C, the GFLOP/s formula spelled out, and checksums matched across all four versions, which rules out the classic error of timing four different computations. The thin part is that there is exactly one reading of each number — one Mac, one compiler at -O2, one matrix size, no run-to-run spread — and the 410 GFLOP/s comparator was taken through a one-line numpy call, so multithreaded library code is being clocked against single-threaded C without saying so.
One author, two postings
The techniques are ancient and universal; the finding is what needs takers, and so far it has none. The only footprint our coverage can see is the same run published twice under one byline — dev.to and lkforge.com — with no engineer reporting rates from other silicon. That absence bites here specifically, because the author's explanation for why tiling lost is a property of the chip he tested.
Title travels further than the bench
The write-up argues against its own interest more than most: it volunteers that the celebrated hand loop reaches about 4% of library speed, refuses the line that tiling is useless, and names the conditions under which blocking should win. The overreach is only in the framing — 'beat every cache-tiled version' is a fact about one Apple Silicon Mac at n=1024, and the author's own diagnosis, a large L2 plus a compiler that vectorised the clean loop, is exactly the reason not to carry the headline to another chip.
Traffic interest, no product to sell
The post opens and closes with links back to the author's own site and its browser matrix tools, so there is a straightforward attention motive in publishing an eye-catching result twice. Set against that: no vendor is being compared to a rival, nothing is priced, and the recommendation — use BLAS, don't write your own — devalues the very code the author spent his weekend on.
Mechanism solid, breadth missing
Every number that can be checked from the page checks out: 1024 doubles is an 8 KB stride, three 256-tiles are about 1.57 MB, 2·n³ at n=1024 is about 2.15 GFLOP. The mechanism is textbook and the code is there to run. What caps this is not plausibility but coverage: with one machine in the sample, nobody can tell whether tiling lost to loop reordering or merely lost to this particular L2, and that is the whole question a reader would act on.