{"about":"Lesson K21, threads, workgroups and memory. Computed by tools/school/fill_threads.mjs from the emulator in system/school/threads.mjs. Do not edit by hand. No GPU was used: every number is a count from the emulator's model or a published limit. Timings on a real GPU happen only in the lab, on the reader's device, labelled with their adapter.","sourceSha256":"542d91db03d9f15a7aab51d90bc51eaa222cabf67bdf9ba73efb39dd51953172","sourceFile":"system/school/threads.mjs","spec":{"about":"Published limits and rules, with their sources. WebGPU: W3C Candidate Recommendation Draft, https://www.w3.org/TR/webgpu/, section 3.6.2 Limits (the version read was dated 15 September 2026); the values are the defaults every WebGPU device must support, an adapter may offer more, and compat holds the compatibility-mode defaults. WGSL: https://www.w3.org/TR/WGSL/, section 13.3.1.1.4 global_invocation_id (workgroup_id * workgroup_size + local_invocation_id) and section 6.5.7 Out-of-Bounds Access (an invalid store may write any location of the bound GPUBuffer or not be executed; an invalid load may return any value of the buffer or zero). CUDA: CUDA Programming Guide 13.4.2, https://docs.nvidia.com/cuda/cuda-programming-guide/: section 1 Programming Model (threads of a block are organized into groups of 32 threads called warps), section 2.3.4.1 Coalesced Global Memory Access (32-byte memory transactions; consecutive 4-byte words from a warp's 32 threads are 128 bytes fetched in four 32-byte transactions; the worst case is one transaction per thread), and the Compute Capabilities appendix (1,024 threads per block; block x and y up to 1,024, z up to 64; warp size 32). WebGPU has no warp: invocations are grouped into subgroups whose size the adapter reports (subgroupMinSize, subgroupMaxSize) when the subgroups feature is available.","webgpu":{"maxComputeWorkgroupSizeX":256,"maxComputeWorkgroupSizeY":256,"maxComputeWorkgroupSizeZ":64,"maxComputeInvocationsPerWorkgroup":256,"maxComputeWorkgroupsPerDimension":65535,"maxComputeWorkgroupStorageSize":16384,"maxStorageBufferBindingSize":134217728,"minStorageBufferOffsetAlignment":256,"compat":{"maxComputeWorkgroupSizeX":128,"maxComputeWorkgroupSizeY":128,"maxComputeInvocationsPerWorkgroup":128}},"cuda":{"warpSize":32,"maxThreadsPerBlock":1024,"maxBlockDimX":1024,"maxBlockDimY":1024,"maxBlockDimZ":64,"transactionBytes":32},"wgsl":{"globalInvocationId":"workgroup_id * workgroup_size + local_invocation_id","invalidStore":["store to any memory location of the bound GPUBuffer","not be executed"],"invalidLoad":["any memory location of the bound GPUBuffer","the zero value"]}},"grouping":{"about":"How a 1-D dispatch of ceil(n / wg) workgroups covers an array of n elements. invocations = workgroups * wg; idleThreads run the bound check and return (closedForm = ceil(n / wg) * wg - n, which the emulator matches). warps: 32-lane groups inside each workgroup (the CUDA model); a workgroup size that is not a multiple of 32 leaves partialWarps with emptyLanes. dispatchesNeeded: 1-D dispatches if each may hold at most maxComputeWorkgroupsPerDimension (65,535) workgroups.","rows":[{"n":1000,"wg":32,"workgroups":32,"invocations":1024,"idleThreads":24,"idleShare":0.0234,"closedForm":24,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000,"wg":48,"workgroups":21,"invocations":1008,"idleThreads":8,"idleShare":0.0079,"closedForm":8,"warps":42,"partialWarps":21,"emptyLanes":336,"dispatchesNeeded":1},{"n":1000,"wg":64,"workgroups":16,"invocations":1024,"idleThreads":24,"idleShare":0.0234,"closedForm":24,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000,"wg":128,"workgroups":8,"invocations":1024,"idleThreads":24,"idleShare":0.0234,"closedForm":24,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000,"wg":256,"workgroups":4,"invocations":1024,"idleThreads":24,"idleShare":0.0234,"closedForm":24,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1024,"wg":32,"workgroups":32,"invocations":1024,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1024,"wg":48,"workgroups":22,"invocations":1056,"idleThreads":32,"idleShare":0.0303,"closedForm":32,"warps":44,"partialWarps":22,"emptyLanes":352,"dispatchesNeeded":1},{"n":1024,"wg":64,"workgroups":16,"invocations":1024,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1024,"wg":128,"workgroups":8,"invocations":1024,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1024,"wg":256,"workgroups":4,"invocations":1024,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":4099,"wg":32,"workgroups":129,"invocations":4128,"idleThreads":29,"idleShare":0.007,"closedForm":29,"warps":129,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":4099,"wg":48,"workgroups":86,"invocations":4128,"idleThreads":29,"idleShare":0.007,"closedForm":29,"warps":172,"partialWarps":86,"emptyLanes":1376,"dispatchesNeeded":1},{"n":4099,"wg":64,"workgroups":65,"invocations":4160,"idleThreads":61,"idleShare":0.0147,"closedForm":61,"warps":130,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":4099,"wg":128,"workgroups":33,"invocations":4224,"idleThreads":125,"idleShare":0.0296,"closedForm":125,"warps":132,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":4099,"wg":256,"workgroups":17,"invocations":4352,"idleThreads":253,"idleShare":0.0581,"closedForm":253,"warps":136,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1048576,"wg":32,"workgroups":32768,"invocations":1048576,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32768,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1048576,"wg":48,"workgroups":21846,"invocations":1048608,"idleThreads":32,"idleShare":0.0000305,"closedForm":32,"warps":43692,"partialWarps":21846,"emptyLanes":349536,"dispatchesNeeded":1},{"n":1048576,"wg":64,"workgroups":16384,"invocations":1048576,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32768,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1048576,"wg":128,"workgroups":8192,"invocations":1048576,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32768,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1048576,"wg":256,"workgroups":4096,"invocations":1048576,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":32768,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000000,"wg":32,"workgroups":31250,"invocations":1000000,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":31250,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000000,"wg":48,"workgroups":20834,"invocations":1000032,"idleThreads":32,"idleShare":0.000032,"closedForm":32,"warps":41668,"partialWarps":20834,"emptyLanes":333344,"dispatchesNeeded":1},{"n":1000000,"wg":64,"workgroups":15625,"invocations":1000000,"idleThreads":0,"idleShare":0,"closedForm":0,"warps":31250,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000000,"wg":128,"workgroups":7813,"invocations":1000064,"idleThreads":64,"idleShare":0.000064,"closedForm":64,"warps":31252,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1},{"n":1000000,"wg":256,"workgroups":3907,"invocations":1000192,"idleThreads":192,"idleShare":0.0002,"closedForm":192,"warps":31256,"partialWarps":0,"emptyLanes":0,"dispatchesNeeded":1}],"verdict":"Idle threads are at most wg - 1 per dispatch: 24 at wg 32, 8 at wg 48, 24 at wg 64, 24 at wg 128, 24 at wg 256 for n = 1,000; the largest share in the table is 0.058 (n 4099, wg 256). Every row matches the closed form: true."},"traffic":{"about":"Global memory traffic of out[i] = a[j] + b[j] for n = 1048576 (2^20) 4-byte floats, workgroup size 64, in the 32-lane model: each warp's load of a, load of b and store of out costs one transaction per distinct segment its active lanes touch. t32: 32-byte transactions (the CUDA Programming Guide 13.4, section 2.3.4.1: global memory is accessed via 32-byte memory transactions). t128: 128-byte segments (the older whole-line model; one transaction per perfectly coalesced warp of 4-byte words). stride 1 is the contiguous kernel; stride S reads a transposed walk in which neighbouring threads read elements S apart (the write stays contiguous). efficiency = useful bytes / bytes moved. closedForm: ceil(4n / segment) per array for contiguous access.","rows":[{"stride":1,"loads":2097152,"stores":1048576,"t32":{"a":131072,"b":131072,"out":131072,"total":393216,"bytes":12582912,"efficiency":1},"t128":{"a":32768,"b":32768,"out":32768,"total":98304,"bytes":12582912,"efficiency":1},"usefulBytes":12582912,"ratio32":1,"ratio128":1},{"stride":2,"loads":2097152,"stores":1048576,"t32":{"a":262144,"b":262144,"out":131072,"total":655360,"bytes":20971520,"efficiency":0.6},"t128":{"a":65536,"b":65536,"out":32768,"total":163840,"bytes":20971520,"efficiency":0.6},"usefulBytes":12582912,"ratio32":1.6667,"ratio128":1.6667},{"stride":4,"loads":2097152,"stores":1048576,"t32":{"a":524288,"b":524288,"out":131072,"total":1179648,"bytes":37748736,"efficiency":0.3333},"t128":{"a":131072,"b":131072,"out":32768,"total":294912,"bytes":37748736,"efficiency":0.3333},"usefulBytes":12582912,"ratio32":3,"ratio128":3},{"stride":8,"loads":2097152,"stores":1048576,"t32":{"a":1048576,"b":1048576,"out":131072,"total":2228224,"bytes":71303168,"efficiency":0.1765},"t128":{"a":262144,"b":262144,"out":32768,"total":557056,"bytes":71303168,"efficiency":0.1765},"usefulBytes":12582912,"ratio32":5.6667,"ratio128":5.6667},{"stride":16,"loads":2097152,"stores":1048576,"t32":{"a":1048576,"b":1048576,"out":131072,"total":2228224,"bytes":71303168,"efficiency":0.1765},"t128":{"a":524288,"b":524288,"out":32768,"total":1081344,"bytes":138412032,"efficiency":0.0909},"usefulBytes":12582912,"ratio32":5.6667,"ratio128":11},{"stride":32,"loads":2097152,"stores":1048576,"t32":{"a":1048576,"b":1048576,"out":131072,"total":2228224,"bytes":71303168,"efficiency":0.1765},"t128":{"a":1048576,"b":1048576,"out":32768,"total":2129920,"bytes":272629760,"efficiency":0.0462},"usefulBytes":12582912,"ratio32":5.6667,"ratio128":21.6667},{"stride":64,"loads":2097152,"stores":1048576,"t32":{"a":1048576,"b":1048576,"out":131072,"total":2228224,"bytes":71303168,"efficiency":0.1765},"t128":{"a":1048576,"b":1048576,"out":32768,"total":2129920,"bytes":272629760,"efficiency":0.0462},"usefulBytes":12582912,"ratio32":5.6667,"ratio128":21.6667},{"stride":1024,"loads":2097152,"stores":1048576,"t32":{"a":1048576,"b":1048576,"out":131072,"total":2228224,"bytes":71303168,"efficiency":0.1765},"t128":{"a":1048576,"b":1048576,"out":32768,"total":2129920,"bytes":272629760,"efficiency":0.0462},"usefulBytes":12582912,"ratio32":5.6667,"ratio128":21.6667}],"closedForm":{"t32":131072,"t128":32768},"wg48":{"t32":{"a":131072,"b":131072,"out":131072,"total":393216,"bytes":12582912,"efficiency":1},"t128":{"a":54613,"b":54613,"out":54613,"total":163839,"bytes":20971392,"efficiency":0.6}},"verdict":["Contiguous: 32768 128-byte transactions per array (closed form 32768), 131072 32-byte ones (closed form 131072); efficiency 1 and 1.","Strided reads, transactions over contiguous, all three arrays: 32-byte model stride 1 1x, stride 2 1.67x, stride 4 3x, stride 8 5.67x, stride 16 5.67x, stride 32 5.67x, stride 64 5.67x, stride 1024 5.67x; 128-byte model stride 1 1x, stride 2 1.67x, stride 4 3x, stride 8 5.67x, stride 16 11x, stride 32 21.67x, stride 64 21.67x, stride 1024 21.67x. The read side stops growing once neighbouring threads are a segment apart (8 floats for 32 bytes, 32 floats for 128 bytes): one transaction per thread is the worst case.","Workgroup size 48 (not a multiple of 32): 54613 128-byte transactions per array against 32768 at 64, because its warps start at elements 48g and 48g + 32, which for odd g sit 64 bytes off a 128-byte boundary; in the 32-byte model 131072 against 131072."]},"controls":{"about":"The checker against broken kernels, n = 1000, workgroup size 64, 64 canary floats after the bound array in the same buffer. WGSL section 6.5.7 lets a store past the end of a binding write to any location of the bound buffer or not happen at all; the three oob modes are three of those allowed outcomes: discard (dropped), clamp (lands on the last element), buffer (lands at its own index in the canary words). caughtByOutput: the output check fails (a wrong element or a changed canary). caughtByCount: the emulator counts at least one store past the binding (only the emulator can count; a GPU run has only the output check).","rows":[{"kind":"add","oob":"discard","oobStores":0,"oobLoads":0,"mismatches":0,"canaryHit":0,"caughtByOutput":false,"caughtByCount":false},{"kind":"add","oob":"clamp","oobStores":0,"oobLoads":0,"mismatches":0,"canaryHit":0,"caughtByOutput":false,"caughtByCount":false},{"kind":"add","oob":"buffer","oobStores":0,"oobLoads":0,"mismatches":0,"canaryHit":0,"caughtByOutput":false,"caughtByCount":false},{"kind":"offByOne","oob":"discard","oobStores":1,"oobLoads":2,"mismatches":0,"canaryHit":0,"caughtByOutput":false,"caughtByCount":true},{"kind":"offByOne","oob":"clamp","oobStores":1,"oobLoads":2,"mismatches":1,"canaryHit":0,"caughtByOutput":true,"caughtByCount":true},{"kind":"offByOne","oob":"buffer","oobStores":1,"oobLoads":2,"mismatches":0,"canaryHit":1,"caughtByOutput":true,"caughtByCount":true},{"kind":"short","oob":"discard","oobStores":0,"oobLoads":0,"mismatches":1,"canaryHit":0,"caughtByOutput":true,"caughtByCount":false},{"kind":"short","oob":"clamp","oobStores":0,"oobLoads":0,"mismatches":1,"canaryHit":0,"caughtByOutput":true,"caughtByCount":false},{"kind":"short","oob":"buffer","oobStores":0,"oobLoads":0,"mismatches":1,"canaryHit":0,"caughtByOutput":true,"caughtByCount":false},{"kind":"noGuard","oob":"discard","oobStores":24,"oobLoads":48,"mismatches":0,"canaryHit":0,"caughtByOutput":false,"caughtByCount":true},{"kind":"noGuard","oob":"clamp","oobStores":24,"oobLoads":48,"mismatches":1,"canaryHit":0,"caughtByOutput":true,"caughtByCount":true},{"kind":"noGuard","oob":"buffer","oobStores":24,"oobLoads":48,"mismatches":0,"canaryHit":24,"caughtByOutput":true,"caughtByCount":true}],"verdict":"Of 9 broken cases, the output check (elements and canaries) misses 2: offByOne with discard, noGuard with discard; the out-of-bounds store count misses 3: short with discard, short with clamp, short with buffer; both miss 0: none. A dropped stray write leaves a correct-looking output, and a kernel that stops one short writes nothing out of bounds, so each check covers the other's gap."},"speed":{"about":"Milliseconds in Node (V8), one process. The emulator visits every thread and counts every segment, so it is far slower than a GPU; a lab runs it in 40 ms slices of workgroups. msPerWorkgroup: one 64-wide workgroup with traffic counted in both models. msEmulate2pow20: the whole 2^20 array. msReference and msCheck: CPU reference and output check for 2^20 floats (the lab's correctness pass after a GPU run).","msPerWorkgroup":0.0085,"workgroupsPer40ms":4683,"msEmulate2pow20":77.5556,"msReference":5.1289,"msCheck":3.9264},"film":{"about":"What the films draw. map: a dispatch of n = 40 over workgroups of 16 (3 workgroups, 48 invocations, 8 idle), each invocation's workgroup, local id, global id, warp and the element it reads and writes; offByOne is the same dispatch with the off-by-one guard (one invocation writes element 40). warp0: the first warp's 32 lanes, the element each reads and its 32-byte and 128-byte segment, for contiguous access and strides 8 and 32 (n = 4096); segments counts them. idle: idle threads for n = 1,000 at each workgroup size.","map":[{"workgroup":0,"local":0,"global":0,"warp":0,"runs":true,"reads":0,"writes":0,"outOfBounds":false},{"workgroup":0,"local":1,"global":1,"warp":0,"runs":true,"reads":1,"writes":1,"outOfBounds":false},{"workgroup":0,"local":2,"global":2,"warp":0,"runs":true,"reads":2,"writes":2,"outOfBounds":false},{"workgroup":0,"local":3,"global":3,"warp":0,"runs":true,"reads":3,"writes":3,"outOfBounds":false},{"workgroup":0,"local":4,"global":4,"warp":0,"runs":true,"reads":4,"writes":4,"outOfBounds":false},{"workgroup":0,"local":5,"global":5,"warp":0,"runs":true,"reads":5,"writes":5,"outOfBounds":false},{"workgroup":0,"local":6,"global":6,"warp":0,"runs":true,"reads":6,"writes":6,"outOfBounds":false},{"workgroup":0,"local":7,"global":7,"warp":0,"runs":true,"reads":7,"writes":7,"outOfBounds":false},{"workgroup":0,"local":8,"global":8,"warp":0,"runs":true,"reads":8,"writes":8,"outOfBounds":false},{"workgroup":0,"local":9,"global":9,"warp":0,"runs":true,"reads":9,"writes":9,"outOfBounds":false},{"workgroup":0,"local":10,"global":10,"warp":0,"runs":true,"reads":10,"writes":10,"outOfBounds":false},{"workgroup":0,"local":11,"global":11,"warp":0,"runs":true,"reads":11,"writes":11,"outOfBounds":false},{"workgroup":0,"local":12,"global":12,"warp":0,"runs":true,"reads":12,"writes":12,"outOfBounds":false},{"workgroup":0,"local":13,"global":13,"warp":0,"runs":true,"reads":13,"writes":13,"outOfBounds":false},{"workgroup":0,"local":14,"global":14,"warp":0,"runs":true,"reads":14,"writes":14,"outOfBounds":false},{"workgroup":0,"local":15,"global":15,"warp":0,"runs":true,"reads":15,"writes":15,"outOfBounds":false},{"workgroup":1,"local":0,"global":16,"warp":0,"runs":true,"reads":16,"writes":16,"outOfBounds":false},{"workgroup":1,"local":1,"global":17,"warp":0,"runs":true,"reads":17,"writes":17,"outOfBounds":false},{"workgroup":1,"local":2,"global":18,"warp":0,"runs":true,"reads":18,"writes":18,"outOfBounds":false},{"workgroup":1,"local":3,"global":19,"warp":0,"runs":true,"reads":19,"writes":19,"outOfBounds":false},{"workgroup":1,"local":4,"global":20,"warp":0,"runs":true,"reads":20,"writes":20,"outOfBounds":false},{"workgroup":1,"local":5,"global":21,"warp":0,"runs":true,"reads":21,"writes":21,"outOfBounds":false},{"workgroup":1,"local":6,"global":22,"warp":0,"runs":true,"reads":22,"writes":22,"outOfBounds":false},{"workgroup":1,"local":7,"global":23,"warp":0,"runs":true,"reads":23,"writes":23,"outOfBounds":false},{"workgroup":1,"local":8,"global":24,"warp":0,"runs":true,"reads":24,"writes":24,"outOfBounds":false},{"workgroup":1,"local":9,"global":25,"warp":0,"runs":true,"reads":25,"writes":25,"outOfBounds":false},{"workgroup":1,"local":10,"global":26,"warp":0,"runs":true,"reads":26,"writes":26,"outOfBounds":false},{"workgroup":1,"local":11,"global":27,"warp":0,"runs":true,"reads":27,"writes":27,"outOfBounds":false},{"workgroup":1,"local":12,"global":28,"warp":0,"runs":true,"reads":28,"writes":28,"outOfBounds":false},{"workgroup":1,"local":13,"global":29,"warp":0,"runs":true,"reads":29,"writes":29,"outOfBounds":false},{"workgroup":1,"local":14,"global":30,"warp":0,"runs":true,"reads":30,"writes":30,"outOfBounds":false},{"workgroup":1,"local":15,"global":31,"warp":0,"runs":true,"reads":31,"writes":31,"outOfBounds":false},{"workgroup":2,"local":0,"global":32,"warp":0,"runs":true,"reads":32,"writes":32,"outOfBounds":false},{"workgroup":2,"local":1,"global":33,"warp":0,"runs":true,"reads":33,"writes":33,"outOfBounds":false},{"workgroup":2,"local":2,"global":34,"warp":0,"runs":true,"reads":34,"writes":34,"outOfBounds":false},{"workgroup":2,"local":3,"global":35,"warp":0,"runs":true,"reads":35,"writes":35,"outOfBounds":false},{"workgroup":2,"local":4,"global":36,"warp":0,"runs":true,"reads":36,"writes":36,"outOfBounds":false},{"workgroup":2,"local":5,"global":37,"warp":0,"runs":true,"reads":37,"writes":37,"outOfBounds":false},{"workgroup":2,"local":6,"global":38,"warp":0,"runs":true,"reads":38,"writes":38,"outOfBounds":false},{"workgroup":2,"local":7,"global":39,"warp":0,"runs":true,"reads":39,"writes":39,"outOfBounds":false},{"workgroup":2,"local":8,"global":40,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":9,"global":41,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":10,"global":42,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":11,"global":43,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":12,"global":44,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":13,"global":45,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":14,"global":46,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false},{"workgroup":2,"local":15,"global":47,"warp":0,"runs":false,"reads":null,"writes":null,"outOfBounds":false}],"offByOne":[{"workgroup":2,"local":8,"global":40,"warp":0,"runs":true,"reads":40,"writes":40,"outOfBounds":true}],"warp0":{"contiguous":[{"lane":0,"element":0,"seg32":0,"seg128":0},{"lane":1,"element":1,"seg32":0,"seg128":0},{"lane":2,"element":2,"seg32":0,"seg128":0},{"lane":3,"element":3,"seg32":0,"seg128":0},{"lane":4,"element":4,"seg32":0,"seg128":0},{"lane":5,"element":5,"seg32":0,"seg128":0},{"lane":6,"element":6,"seg32":0,"seg128":0},{"lane":7,"element":7,"seg32":0,"seg128":0},{"lane":8,"element":8,"seg32":1,"seg128":0},{"lane":9,"element":9,"seg32":1,"seg128":0},{"lane":10,"element":10,"seg32":1,"seg128":0},{"lane":11,"element":11,"seg32":1,"seg128":0},{"lane":12,"element":12,"seg32":1,"seg128":0},{"lane":13,"element":13,"seg32":1,"seg128":0},{"lane":14,"element":14,"seg32":1,"seg128":0},{"lane":15,"element":15,"seg32":1,"seg128":0},{"lane":16,"element":16,"seg32":2,"seg128":0},{"lane":17,"element":17,"seg32":2,"seg128":0},{"lane":18,"element":18,"seg32":2,"seg128":0},{"lane":19,"element":19,"seg32":2,"seg128":0},{"lane":20,"element":20,"seg32":2,"seg128":0},{"lane":21,"element":21,"seg32":2,"seg128":0},{"lane":22,"element":22,"seg32":2,"seg128":0},{"lane":23,"element":23,"seg32":2,"seg128":0},{"lane":24,"element":24,"seg32":3,"seg128":0},{"lane":25,"element":25,"seg32":3,"seg128":0},{"lane":26,"element":26,"seg32":3,"seg128":0},{"lane":27,"element":27,"seg32":3,"seg128":0},{"lane":28,"element":28,"seg32":3,"seg128":0},{"lane":29,"element":29,"seg32":3,"seg128":0},{"lane":30,"element":30,"seg32":3,"seg128":0},{"lane":31,"element":31,"seg32":3,"seg128":0}],"stride8":[{"lane":0,"element":0,"seg32":0,"seg128":0},{"lane":1,"element":8,"seg32":1,"seg128":0},{"lane":2,"element":16,"seg32":2,"seg128":0},{"lane":3,"element":24,"seg32":3,"seg128":0},{"lane":4,"element":32,"seg32":4,"seg128":1},{"lane":5,"element":40,"seg32":5,"seg128":1},{"lane":6,"element":48,"seg32":6,"seg128":1},{"lane":7,"element":56,"seg32":7,"seg128":1},{"lane":8,"element":64,"seg32":8,"seg128":2},{"lane":9,"element":72,"seg32":9,"seg128":2},{"lane":10,"element":80,"seg32":10,"seg128":2},{"lane":11,"element":88,"seg32":11,"seg128":2},{"lane":12,"element":96,"seg32":12,"seg128":3},{"lane":13,"element":104,"seg32":13,"seg128":3},{"lane":14,"element":112,"seg32":14,"seg128":3},{"lane":15,"element":120,"seg32":15,"seg128":3},{"lane":16,"element":128,"seg32":16,"seg128":4},{"lane":17,"element":136,"seg32":17,"seg128":4},{"lane":18,"element":144,"seg32":18,"seg128":4},{"lane":19,"element":152,"seg32":19,"seg128":4},{"lane":20,"element":160,"seg32":20,"seg128":5},{"lane":21,"element":168,"seg32":21,"seg128":5},{"lane":22,"element":176,"seg32":22,"seg128":5},{"lane":23,"element":184,"seg32":23,"seg128":5},{"lane":24,"element":192,"seg32":24,"seg128":6},{"lane":25,"element":200,"seg32":25,"seg128":6},{"lane":26,"element":208,"seg32":26,"seg128":6},{"lane":27,"element":216,"seg32":27,"seg128":6},{"lane":28,"element":224,"seg32":28,"seg128":7},{"lane":29,"element":232,"seg32":29,"seg128":7},{"lane":30,"element":240,"seg32":30,"seg128":7},{"lane":31,"element":248,"seg32":31,"seg128":7}],"stride32":[{"lane":0,"element":0,"seg32":0,"seg128":0},{"lane":1,"element":32,"seg32":4,"seg128":1},{"lane":2,"element":64,"seg32":8,"seg128":2},{"lane":3,"element":96,"seg32":12,"seg128":3},{"lane":4,"element":128,"seg32":16,"seg128":4},{"lane":5,"element":160,"seg32":20,"seg128":5},{"lane":6,"element":192,"seg32":24,"seg128":6},{"lane":7,"element":224,"seg32":28,"seg128":7},{"lane":8,"element":256,"seg32":32,"seg128":8},{"lane":9,"element":288,"seg32":36,"seg128":9},{"lane":10,"element":320,"seg32":40,"seg128":10},{"lane":11,"element":352,"seg32":44,"seg128":11},{"lane":12,"element":384,"seg32":48,"seg128":12},{"lane":13,"element":416,"seg32":52,"seg128":13},{"lane":14,"element":448,"seg32":56,"seg128":14},{"lane":15,"element":480,"seg32":60,"seg128":15},{"lane":16,"element":512,"seg32":64,"seg128":16},{"lane":17,"element":544,"seg32":68,"seg128":17},{"lane":18,"element":576,"seg32":72,"seg128":18},{"lane":19,"element":608,"seg32":76,"seg128":19},{"lane":20,"element":640,"seg32":80,"seg128":20},{"lane":21,"element":672,"seg32":84,"seg128":21},{"lane":22,"element":704,"seg32":88,"seg128":22},{"lane":23,"element":736,"seg32":92,"seg128":23},{"lane":24,"element":768,"seg32":96,"seg128":24},{"lane":25,"element":800,"seg32":100,"seg128":25},{"lane":26,"element":832,"seg32":104,"seg128":26},{"lane":27,"element":864,"seg32":108,"seg128":27},{"lane":28,"element":896,"seg32":112,"seg128":28},{"lane":29,"element":928,"seg32":116,"seg128":29},{"lane":30,"element":960,"seg32":120,"seg128":30},{"lane":31,"element":992,"seg32":124,"seg128":31}]},"segments":{"contiguous":{"t32":4,"t128":1},"stride8":{"t32":32,"t128":8},"stride32":{"t32":32,"t128":32}},"idle":[{"wg":32,"idle":24},{"wg":48,"idle":8},{"wg":64,"idle":24},{"wg":128,"idle":24},{"wg":256,"idle":24}]},"lab":{"about":"The lab's measurement, run only in a browser on the reader's own GPU through WebGPU (system/school/threads-gpu.mjs). For each kernel and workgroup size it first checks the output against the CPU reference (with 64 canary floats past the binding), then times reps dispatches after one warm-up and reports the median wall time from submit to onSubmittedWorkDone (submission overhead included) and the effective bandwidth 12 n bytes / time. Every result is labelled with the adapter's vendor, architecture and description and its subgroup sizes. It is not run by the fill or the tests.","n":1048576,"workgroupSizes":[32,64,128,256],"kernels":["add","strided"],"strides":[2,8,32,1024],"reps":9,"warmup":1,"pad":64,"measures":["medianMs per dispatch","gbPerS = 12 n / medianMs","strided over contiguous time ratio at each stride","time across workgroup sizes","checker result for every run"],"predicts":"In the 32-lane, 32-byte model the strided kernel moves (32 + 32 + 4) / 12 = 5.67 times the bytes of the contiguous one at stride 8 and above (each thread's read of a and of b costs a whole 32-byte transaction, its contiguous write 4 bytes); traffic.rows holds the emulator's count. A measured time ratio far from that says caches, a different grouping or a different transaction size are at work. The model gives counts, not times."},"seconds":1.2}
