Commit 71a94c8
fix(ops): cancellation-free table-lookup builders (min-clamp + saturating steps)
The map_select table-lookup builders _table_lookup_row_vector /
_table_lookup_column_mask / _table_lookup_index_staircase built a single
piecewise_linear over 2*(n-1)+1 breakpoints with input_scale=sharpness -- the
same single-projection sum delta*relu(s*x - b) floor_int had. The partial sums
grow to ~s*x*n and overflow fp32's 2^24 exact-integer limit, so the
alternating-sign terms cancel into garbage. Two triggers: (a) a scaled index far
outside [0,n-1] pushes sharpness*index past 2^24; (b) a tall table's top
breakpoint position passes 2^24. _table_lookup_index_staircase(n=256, s=100) at
x=100000 returned 0.0 (should clamp to 255 -- the index was never clamped before
the staircase); n=20000, s=1000 collapsed an in-range x=19999 to 0.0. Dormant at
current call sites (small tables, in-range pre-rounded indices) but a landmine
for the DOOM texture/palette lookup track's larger tables.
Rebuild all three on a shared _saturating_step_select helper, the table analogue
of floor_int's saturating-step staircase:
out = top - sum_k relu(1 - step_k) * deltas[k-1],
step_k = relu(t_k) - relu(t_k - W), t_k = s*(x - (k-0.5)) + 0.5,
rows reconstructed from consecutive differences (deltas[k-1] = value[k] -
value[k-1], value[n-1] = top). Each step is a 2-term per-output difference, so
the accumulation's partial sums are bounded by the table's total variation, not
by s*x -- removing the cancellation regardless of n (trigger b). A leading
min(index, n-1) clamp (one sublayer, (n-1) - relu((n-1) - x), a single ReLU of a
magnitude, no cancellation) bounds the out-of-range case so W -- sized for the
in-range span -- always resolves the saturating difference (trigger a); the
lower edge needs no clamp. The +0.5 centers the ramp on the boundary,
reproducing the old two-row linear blend in the transition band, so off-grid
values are unchanged.
Cost: one min sublayer + the two chained ReLU sublayers of the staircase, vs the
old single sublayer. Reproducer tests at the smallest layer
(test_table_lookup_2d_out_of_range_index_clamps_to_edge, _tall_table_stays_exact,
_index_staircase_clamps_and_rounds_at_any_magnitude, _3d_large_flattened_rows_exact);
existing table_lookup tests (incl transition band + compile-fidelity) stay green.
table_lookup_2d/_3d are not measured ops so op_noise_data.json is unchanged;
docs/numerical_noise_findings.md "Known gap" -> "Resolved". Drops now-dead
_lookup_breakpoints / _lookup_integer_index_at and the unused piecewise_linear /
Assert module imports.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent d5da1db commit 71a94c8
3 files changed
Lines changed: 305 additions & 67 deletions
File tree
- docs
- tests/ops
- torchwright/ops
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
174 | | - | |
| 174 | + | |
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
178 | | - | |
| 178 | + | |
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
194 | 224 | | |
195 | 225 | | |
196 | 226 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1130 | 1130 | | |
1131 | 1131 | | |
1132 | 1132 | | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
0 commit comments