File size: 17,713 Bytes
f85db5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
{
  "op": "ai.onnx.Scan",
  "cases": [
    {
      "name": "lowered_prefix_sum_state",
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, 10.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [3, 2],
          "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [3, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_reverse",
      "attrs": { "reverse": 1 },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [4, 1],
          "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [4, 1], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_ort_projection_short_sequence_two_state_lanes",
      "provenance": {
        "source": "onnxruntime/test/providers/cpu/controlflow/scan_test.cc",
        "test": "Scan8.ShortSequenceTwoInBatchOneLoopStateVar",
        "notes": "Projection onto the framework's lowered prefix-sum variant using two state lanes from ORT's short sequence data."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 10.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [2, 2],
          "data": { "kind": "values", "values": [1.0, -1.0, 4.0, -4.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [2, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_ort_projection_reverse_two_state_lanes",
      "attrs": { "reverse": 1 },
      "provenance": {
        "source": "onnxruntime/test/providers/cpu/controlflow/scan_test.cc",
        "test": "Scan8.MixedSequenceLensReverse",
        "notes": "Projection onto the framework's lowered reverse prefix-sum variant using reverse-direction values from ORT's Scan coverage."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 10.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [2, 2],
          "data": { "kind": "values", "values": [1.0, -1.0, 4.0, -4.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [2, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_ort_projection_scalar_loop_state",
      "provenance": {
        "source": "onnxruntime/test/providers/cpu/controlflow/scan_test.cc",
        "test": "Scan8.OnnxScalarLoopState",
        "notes": "Projection onto the framework's lowered prefix-sum variant using a scalar carried state."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.0] } },
        "scan_input": { "dtype": "float32", "shape": [3, 1], "data": { "kind": "values", "values": [1.0, 2.0, 3.0] } }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [3, 1], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_zero_steps",
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, -3.0] } },
        "scan_input": { "dtype": "float32", "shape": [0, 2], "data": { "kind": "values", "values": [] } }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [0, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_reverse_rank2_signed",
      "attrs": { "reverse": 1 },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [10.0, -10.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [3, 2],
          "data": { "kind": "values", "values": [1.0, -1.0, 2.0, -2.0, 3.0, -3.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [3, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_reverse_zero_steps",
      "attrs": { "reverse": 1 },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [7.0, -8.0] } },
        "scan_input": { "dtype": "float32", "shape": [0, 2], "data": { "kind": "values", "values": [] } }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [0, 2], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_zero_delta_lane",
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, 10.0, -5.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [3, 3],
          "data": { "kind": "values", "values": [0.0, 2.0, -1.0, 0.0, -3.0, 4.0, 0.0, 1.0, -2.0] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [3], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [3, 3], "tolerance": 0.000001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_128x64",
      "provenance": {
        "notes": "Cross-gate case for the coop_channel_prefix_sum variant (dim>=64 and steps>=64). dim=64 -> 64 channel workgroups; steps=128 spans multiple WG-sized chunks with a cross-chunk carry. Tolerance covers the within-chunk subgroup/Hillis-Steele reassociation vs the strict serial loop."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [64] },
        "scan_input": { "dtype": "float32", "shape": [128, 64] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [64], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [128, 64], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_reverse_300x96",
      "attrs": { "reverse": 1 },
      "provenance": {
        "notes": "Reverse-direction cross-gate case for coop_channel_prefix_sum. steps=300 is NOT a multiple of the 256 workgroup size, exercising the partial-chunk identity padding; dim=96 channel workgroups."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [96] },
        "scan_input": { "dtype": "float32", "shape": [300, 96] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [96], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [300, 96], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_dim512_steps256_perf_compact",
      "provenance": {
        "notes": "Compact correctness sibling for the Scan no-MMA prefix-sum cliff: dim=512 and steps=256 select coop_channel_prefix_sum with one full workgroup-sized scan chunk."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [512] },
        "scan_input": { "dtype": "float32", "shape": [256, 512] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [512], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [256, 512], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_dim1024_steps256",
      "provenance": {
        "notes": "Exercises a wide cooperative dispatch (1024 channel workgroups) and one full workgroup-sized scan chunk. Tolerance covers within-chunk subgroup/Hillis-Steele reassociation."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1024] },
        "scan_input": { "dtype": "float32", "shape": [256, 1024] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1024], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [256, 1024], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_dim1025_above_old_fixed_gate",
      "provenance": {
        "notes": "Regression for the former hard-coded dim<=1024 ceiling. Device-limit-derived cooperative coverage keeps this realistic 1025-channel scan off the serial fallback."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1025] },
        "scan_input": { "dtype": "float32", "shape": [256, 1025] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1025], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [256, 1025], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_dim64_steps64_min_gate",
      "provenance": {
        "notes": "Both lower coop gates at their exact inclusive thresholds: dim=64 (dim>=64) and steps=64 (steps>=64). This is the smallest shape that still selects coop_channel_prefix_sum. An off-by-one tightening of either >=64 gate (to >64) would demote this corner to the lowered fallback. Verifies coop at the minimum supported width and exactly one partial-free chunk boundary (steps==WG/4)."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [64] },
        "scan_input": { "dtype": "float32", "shape": [64, 64] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [64], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [64, 64], "tolerance": 0.0001 }
      }
    },
    {
      "name": "lowered_dim64_steps63_below_steps_gate",
      "provenance": {
        "notes": "Just below the coop steps gate: dim=64 passes dim>=64 but steps=63 fails steps>=64, so this MUST fall to lowered_prefix_sum. Pins the steps off-by-one: an erroneous steps>=63 (or >63 vs >=64) gate would mis-route this short sequence. Both variants are spec-correct; this checks the lowered path at the exact step below the coop threshold."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [64] },
        "scan_input": { "dtype": "float32", "shape": [63, 64] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [64], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [63, 64], "tolerance": 0.000001 }
      }
    },
    {
      "name": "lowered_prefix_sum_subnormal_residuals_gpu_gap",
      "skipGpu": {
        "category": "permanent",
        "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormals to zero in the ALU; this lowered prefix-sum accumulates subnormal residuals that flush on GPU. Permanent FTZ limitation."
      },
      "provenance": {
        "source": "onnxruntime/test/providers/cpu/controlflow/scan_test.cc",
        "test": "Scan8.ShortSequenceTwoInBatchOneLoopStateVar",
        "notes": "Projection onto the lowered prefix-sum variant: finite subnormal loop-state increments are valid residuals and must not flush to zero."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 0.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [4, 2],
          "data": { "kind": "values", "values": [1e-40, -1e-40, 1e-40, -1e-40, -1e-40, 1e-40, 2e-40, -2e-40] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0 },
        "scan_output": { "dtype": "float32", "shape": [4, 2], "tolerance": 0 }
      }
    },
    {
      "name": "lowered_prefix_sum_reverse_subnormal_residuals_gpu_gap",
      "skipGpu": {
        "category": "permanent",
        "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormals to zero in the ALU; this lowered prefix-sum accumulates subnormal residuals that flush on GPU. Permanent FTZ limitation."
      },
      "attrs": { "reverse": 1 },
      "provenance": {
        "source": "onnxruntime/test/providers/cpu/controlflow/scan_test.cc",
        "test": "Scan8.MixedSequenceLensReverse",
        "notes": "Reverse companion for subnormal prefix residuals; the scan-output slots are written in reverse traversal order but still contain finite float32 subnormal sums."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [3, 1],
          "data": { "kind": "values", "values": [1e-40, 2e-40, 3e-40] }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1], "tolerance": 0 },
        "scan_output": { "dtype": "float32", "shape": [3, 1], "tolerance": 0 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_dim64_steps257_chunk_carry",
      "provenance": {
        "notes": "Routes to coop_channel_prefix_sum (dim=64>=64, dim<=1024, steps=257>=64). chunks=ceil(257/256)=2: chunk 0 = steps 0..255, chunk 1 = ONLY step 256 (one valid lane, 255 identity-padded). Isolates cross-chunk carry propagation into a near-empty second chunk and the final_state = carry-after-both-chunks path. An off-by-one chunk bound, stale carry, or padded-lane double-count would corrupt scan_output[256*64+i] and final_state. Verifies BOTH outputs against the TS reference; tolerance 1e-4 covers within-chunk subgroup/Hillis-Steele reassociation."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [64] },
        "scan_input": { "dtype": "float32", "shape": [257, 64] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [64], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [257, 64], "tolerance": 0.0001 }
      }
    },
    {
      "name": "coop_channel_prefix_sum_reverse_dim64_steps257_chunk_carry",
      "attrs": { "reverse": 1 },
      "provenance": {
        "notes": "Reverse coop_channel_prefix_sum (dim=64>=64, dim<=1024, steps=257>=64, reverse=1). chunks=2: chunk 0 (j=0..255) -> original steps 256..1, chunk 1 (j=256) -> original step 0. Pins the minimal 1-step residual chunk under reverse: verifies the reversed read/write addresses at the chunk boundary and the scan-order cross-chunk carry land at the correct reversed scan_output slots and final_state. Both outputs checked vs the TS reference; tolerance 1e-4 covers within-chunk reassociation."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [64] },
        "scan_input": { "dtype": "float32", "shape": [257, 64] }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [64], "tolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [257, 64], "tolerance": 0.0001 }
      }
    },
    {
      "name": "lowered_dim1_steps2000_singlechannel_serial",
      "provenance": {
        "notes": "dim=1 fails coop 'dim>=64' -> lowered_prefix_sum, one active lane (i=0) running the serial 2000-step recurrence with addressing t*1+0=t. Covers the single-channel serial scan over a long sequence (existing dim=1 cases stop at steps<=4). Serial per-channel accumulation is bit-identical to the reference, so tolerance stays at 1e-6; both outputs verified vs the TS reference."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [3.5] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [2000, 1],
          "data": { "kind": "fillFloat32", "sinStep": 0.017, "scale": 0.25, "offset": 0.01 }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 },
        "scan_output": { "dtype": "float32", "shape": [2000, 1], "tolerance": 0.000001 }
      }
    },
    {
      "name": "multichunk_small_state_dim2_steps4096",
      "provenance": {
        "notes": "Compact correctness lock for a realistic long-stream recurrence with only two independent state lanes. The optimized path partitions the sequential axis into workgroup-sized chunks, scans chunk totals, then applies carries."
      },
      "inputs": {
        "initial_state": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.5, -2.0] } },
        "scan_input": {
          "dtype": "float32",
          "shape": [4096, 2],
          "data": { "kind": "fillFloat32", "sinStep": 0.017, "cosStep": 0.013, "scale": 0.01, "offset": 0.0001 }
        }
      },
      "outputs": {
        "final_state": { "dtype": "float32", "shape": [2], "tolerance": 0.001, "relTolerance": 0.0001 },
        "scan_output": { "dtype": "float32", "shape": [4096, 2], "tolerance": 0.001, "relTolerance": 0.0001 }
      }
    }
  ]
}