Your transformer column splits perfectly on one property of d_model, and it is not size. Two of your six widths are multiples of 64. Those two are the only fast ones.
Pulled arch_scaling_benchmark.csv at a5cc421d, sha256 fa2de20f.... 432 rows, 426 ok.
The controlled comparison is already in your grid. Three transformer configs, all 16 layers, adjacent widths. Prefill, achieved throughput as 2 * actual_params * tok/s:
d_model seq 1024 2048 4096 8192 16384
832 * 16.9 15.3 12.9 9.6 6.5
1072 5.5 3.2 1.8 0.9 OOM
1408 * 15.6 15.4 13.5 11.8 8.6
* = multiple of 64
1072 sits between the other two in width and in parameters and runs 7x slower at 4096, never closer than 2.8x anywhere. Non-monotonic in size, so it is not a scaling curve.
It holds across all six widths. At seq 4096:
64-aligned 832: 12.9 1408: 13.5
not aligned 424: 2.2 688: 2.2 904: 2.9 1072: 1.8
Two groups, no overlap, and the gap opens from seq 2048 up. Your two recurrent arches show no such split at the same widths:
rwkv 4096 448*: 8.8 712: 9.7 832*: 8.9 928: 10.7 1072: 9.2 1408*: 10.7
fwkv 4096 688: 9.6 976: 11.4 1000: 9.2 1216*: 12.5 (L8) / 10.8 (L16) 1600*: 11.0
Interleaved. Only the transformer cares.
It is in decode too, seq 128, same 16-layer triple, tok/s:
d_model transformer rwkv
832 * 160.37 109.25
1072 103.62 108.74
1408 * 161.29 107.54
rwkv is flat inside 2%. The transformer drops 36% on the one unaligned width.
Your OOM strings name the fast path. Six failed cells, all transformer, all seq 16384, and every one at an unaligned width. Both aligned widths survive 16384, including the 500m.
100m d=688 asked 8 GiB 4.94 GiB free process already holding 9.62 GiB
150m d=904 asked 8 GiB 4.74 GiB free process already holding 9.81 GiB
300m d=1072 asked 16 GiB 12.10 GiB free process holding 2.46 GiB
Those allocations are not arbitrary. 16384^2 at fp16 is exactly 0.5 GiB, so 8 GiB is 16 of them and 16 GiB is 32. That is a materialized attention matrix, one per head. The aligned widths never request it at any length. d=424 is unaligned and survives, which fits: fewer heads, smaller ask.
So the six OOMs are two causes under one label. The 300m one is real, 16 GiB does not fit on a 14.56 GiB card. The other two are leftover allocations from the previous cell: on a clean card there was about 12 GiB free and the 8 GiB would have fit.
Two smaller things in the file.
Those six rows write -1.0, not null. Mean best_tokens_per_sec over the prefill rows without filtering on ok and the transformer comes out at 27,500 against 28,696. rwkv 26,699 and fwkv 35,366 are untouched, because the transformer is the only arch that failed.
And best_tokens_per_sec is seq_len/latency on prefill rows and 1000/latency on decode rows. I checked all 426 ok rows against both: zero mismatches. One column name, two units.
The CSV carries no n_heads, so I cannot get head_dim out of it, and head_dim is where a 64 boundary would actually bite.
Would 16 layers at d=1024 and d=1088 settle it? Both aligned, one on either side of 1072. If they land near 13 TFLOP/s and 1072 stays at 1.8, the whole gap is one kernel.