webgpu-bench 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/benchmarks/common.d.ts +6 -8
- package/dist/benchmarks/common.d.ts.map +1 -1
- package/dist/benchmarks/common.js +0 -8
- package/dist/benchmarks/common.js.map +1 -1
- package/dist/benchmarks/flopsCommon.d.ts +0 -9
- package/dist/benchmarks/flopsCommon.d.ts.map +1 -1
- package/dist/benchmarks/flopsCommon.js +1 -5
- package/dist/benchmarks/flopsCommon.js.map +1 -1
- package/dist/benchmarks/flopsConvert.d.ts +7 -6
- package/dist/benchmarks/flopsConvert.d.ts.map +1 -1
- package/dist/benchmarks/flopsConvert.js +10 -30
- package/dist/benchmarks/flopsConvert.js.map +1 -1
- package/dist/benchmarks/flopsF16.d.ts +1 -1
- package/dist/benchmarks/flopsF16.d.ts.map +1 -1
- package/dist/benchmarks/flopsF16.js +3 -11
- package/dist/benchmarks/flopsF16.js.map +1 -1
- package/dist/benchmarks/flopsF32.d.ts +1 -1
- package/dist/benchmarks/flopsF32.d.ts.map +1 -1
- package/dist/benchmarks/flopsF32.js +3 -11
- package/dist/benchmarks/flopsF32.js.map +1 -1
- package/dist/benchmarks/flopsI8.d.ts +2 -2
- package/dist/benchmarks/flopsI8.d.ts.map +1 -1
- package/dist/benchmarks/flopsI8.js +6 -25
- package/dist/benchmarks/flopsI8.js.map +1 -1
- package/dist/benchmarks/flopsMath.d.ts.map +1 -1
- package/dist/benchmarks/flopsMath.js +0 -16
- package/dist/benchmarks/flopsMath.js.map +1 -1
- package/dist/benchmarks/streamBandwidth.d.ts +6 -5
- package/dist/benchmarks/streamBandwidth.d.ts.map +1 -1
- package/dist/benchmarks/streamBandwidth.js +30 -21
- package/dist/benchmarks/streamBandwidth.js.map +1 -1
- package/dist/catalog.d.ts +18 -7
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +235 -32
- package/dist/catalog.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shaders/flopsF16Vec4.d.ts +5 -4
- package/dist/shaders/flopsF16Vec4.d.ts.map +1 -1
- package/dist/shaders/flopsF16Vec4.js +46 -6
- package/dist/shaders/flopsF16Vec4.js.map +1 -1
- package/dist/shaders/flopsF32Div.d.ts +6 -3
- package/dist/shaders/flopsF32Div.d.ts.map +1 -1
- package/dist/shaders/flopsF32Div.js +37 -34
- package/dist/shaders/flopsF32Div.js.map +1 -1
- package/dist/shaders/flopsF32F16Convert.d.ts +3 -3
- package/dist/shaders/flopsF32F16Convert.js +3 -3
- package/dist/shaders/flopsF32Vec4.d.ts +8 -6
- package/dist/shaders/flopsF32Vec4.d.ts.map +1 -1
- package/dist/shaders/flopsF32Vec4.js +49 -8
- package/dist/shaders/flopsF32Vec4.js.map +1 -1
- package/dist/shaders/flopsI32Div.d.ts +5 -3
- package/dist/shaders/flopsI32Div.d.ts.map +1 -1
- package/dist/shaders/flopsI32Div.js +37 -35
- package/dist/shaders/flopsI32Div.js.map +1 -1
- package/dist/shaders/flopsI32F32Convert.d.ts +2 -2
- package/dist/shaders/flopsI32F32Convert.js +2 -2
- package/dist/shaders/flopsI8Dp4a.d.ts +8 -5
- package/dist/shaders/flopsI8Dp4a.d.ts.map +1 -1
- package/dist/shaders/flopsI8Dp4a.js +40 -9
- package/dist/shaders/flopsI8Dp4a.js.map +1 -1
- package/dist/shaders/flopsI8Vec4.d.ts +4 -4
- package/dist/shaders/flopsI8Vec4.d.ts.map +1 -1
- package/dist/shaders/flopsI8Vec4.js +45 -6
- package/dist/shaders/flopsI8Vec4.js.map +1 -1
- package/dist/shaders/flopsU32PackUnpack.d.ts +10 -8
- package/dist/shaders/flopsU32PackUnpack.d.ts.map +1 -1
- package/dist/shaders/flopsU32PackUnpack.js +49 -23
- package/dist/shaders/flopsU32PackUnpack.js.map +1 -1
- package/dist/shaders/streamRead.d.ts +9 -7
- package/dist/shaders/streamRead.d.ts.map +1 -1
- package/dist/shaders/streamRead.js +15 -17
- package/dist/shaders/streamRead.js.map +1 -1
- package/dist/shaders/streamWrite.d.ts +4 -5
- package/dist/shaders/streamWrite.d.ts.map +1 -1
- package/dist/shaders/streamWrite.js +10 -15
- package/dist/shaders/streamWrite.js.map +1 -1
- package/dist/suite.d.ts.map +1 -1
- package/dist/suite.js +2 -7
- package/dist/suite.js.map +1 -1
- package/dist/types.d.ts +5 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fp16 vec4 FLOPS probe —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* fp16 vec4 FLOPS probe — {@link flopsF32Vec4Wgsl}'s eight independent,
|
|
3
|
+
* 4x-unrolled `vec4` FMA chains, but every operand and accumulator is `f16`.
|
|
4
|
+
* 256 FLOPs per loop iteration. Only GPUs with packed-half ALUs run this
|
|
5
|
+
* faster than the fp32 version.
|
|
5
6
|
*/
|
|
6
|
-
export declare const flopsF16Vec4Wgsl = "\nenable f16;\n\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let s: f16 = f16(idx & 15u) * f16(0.001);\n let half: f16 = f16(0.5);\n let one: f16 = f16(1.0);\n let a: vec4<f16> = vec4<f16>(one - s, one - f16(2.0) * s, one - f16(3.0) * s, one - f16(4.0) * s);\n let b: vec4<f16> = vec4<f16>(half + s, half + f16(2.0) * s, half + f16(3.0) * s, half + f16(4.0) * s);\n var
|
|
7
|
+
export declare const flopsF16Vec4Wgsl = "\nenable f16;\n\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let s: f16 = f16(idx & 15u) * f16(0.001);\n let half: f16 = f16(0.5);\n let one: f16 = f16(1.0);\n let a: vec4<f16> = vec4<f16>(one - s, one - f16(2.0) * s, one - f16(3.0) * s, one - f16(4.0) * s);\n let b: vec4<f16> = vec4<f16>(half + s, half + f16(2.0) * s, half + f16(3.0) * s, half + f16(4.0) * s);\n var x0: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.01));\n var x1: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.02));\n var x2: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.03));\n var x3: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.04));\n var x4: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.05));\n var x5: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.06));\n var x6: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.07));\n var x7: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.08));\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n }\n let t = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;\n out[idx] = f32(t.x + t.y + t.z + t.w);\n}\n";
|
|
7
8
|
//# sourceMappingURL=flopsF16Vec4.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF16Vec4.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF16Vec4.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF16Vec4.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF16Vec4.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,umEAmE5B,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fp16 vec4 FLOPS probe —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* fp16 vec4 FLOPS probe — {@link flopsF32Vec4Wgsl}'s eight independent,
|
|
3
|
+
* 4x-unrolled `vec4` FMA chains, but every operand and accumulator is `f16`.
|
|
4
|
+
* 256 FLOPs per loop iteration. Only GPUs with packed-half ALUs run this
|
|
5
|
+
* faster than the fp32 version.
|
|
5
6
|
*/
|
|
6
7
|
export const flopsF16Vec4Wgsl = /* wgsl */ `
|
|
7
8
|
enable f16;
|
|
@@ -25,11 +26,50 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
25
26
|
let one: f16 = f16(1.0);
|
|
26
27
|
let a: vec4<f16> = vec4<f16>(one - s, one - f16(2.0) * s, one - f16(3.0) * s, one - f16(4.0) * s);
|
|
27
28
|
let b: vec4<f16> = vec4<f16>(half + s, half + f16(2.0) * s, half + f16(3.0) * s, half + f16(4.0) * s);
|
|
28
|
-
var
|
|
29
|
+
var x0: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.01));
|
|
30
|
+
var x1: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.02));
|
|
31
|
+
var x2: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.03));
|
|
32
|
+
var x3: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.04));
|
|
33
|
+
var x4: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.05));
|
|
34
|
+
var x5: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.06));
|
|
35
|
+
var x6: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.07));
|
|
36
|
+
var x7: vec4<f16> = vec4<f16>(f16(idx & 255u) * f16(0.0001) + f16(0.08));
|
|
29
37
|
for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {
|
|
30
|
-
|
|
38
|
+
x0 = x0 * a + b;
|
|
39
|
+
x1 = x1 * a + b;
|
|
40
|
+
x2 = x2 * a + b;
|
|
41
|
+
x3 = x3 * a + b;
|
|
42
|
+
x4 = x4 * a + b;
|
|
43
|
+
x5 = x5 * a + b;
|
|
44
|
+
x6 = x6 * a + b;
|
|
45
|
+
x7 = x7 * a + b;
|
|
46
|
+
x0 = x0 * a + b;
|
|
47
|
+
x1 = x1 * a + b;
|
|
48
|
+
x2 = x2 * a + b;
|
|
49
|
+
x3 = x3 * a + b;
|
|
50
|
+
x4 = x4 * a + b;
|
|
51
|
+
x5 = x5 * a + b;
|
|
52
|
+
x6 = x6 * a + b;
|
|
53
|
+
x7 = x7 * a + b;
|
|
54
|
+
x0 = x0 * a + b;
|
|
55
|
+
x1 = x1 * a + b;
|
|
56
|
+
x2 = x2 * a + b;
|
|
57
|
+
x3 = x3 * a + b;
|
|
58
|
+
x4 = x4 * a + b;
|
|
59
|
+
x5 = x5 * a + b;
|
|
60
|
+
x6 = x6 * a + b;
|
|
61
|
+
x7 = x7 * a + b;
|
|
62
|
+
x0 = x0 * a + b;
|
|
63
|
+
x1 = x1 * a + b;
|
|
64
|
+
x2 = x2 * a + b;
|
|
65
|
+
x3 = x3 * a + b;
|
|
66
|
+
x4 = x4 * a + b;
|
|
67
|
+
x5 = x5 * a + b;
|
|
68
|
+
x6 = x6 * a + b;
|
|
69
|
+
x7 = x7 * a + b;
|
|
31
70
|
}
|
|
32
|
-
|
|
71
|
+
let t = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;
|
|
72
|
+
out[idx] = f32(t.x + t.y + t.z + t.w);
|
|
33
73
|
}
|
|
34
74
|
`;
|
|
35
75
|
//# sourceMappingURL=flopsF16Vec4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF16Vec4.js","sourceRoot":"","sources":["../../src/shaders/flopsF16Vec4.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF16Vec4.js","sourceRoot":"","sources":["../../src/shaders/flopsF16Vec4.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmE1C,CAAC"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* fp32 divide-add FLOPS probe. Same shape as {@link flopsF32ScalarWgsl}
|
|
3
3
|
* (eight independent chains, unrolled 4x) but with the multiply replaced by
|
|
4
|
-
* a divide: `x =
|
|
5
|
-
*
|
|
4
|
+
* a divide: `x = a / x + b`. The *divisor* must be the loop-carried value:
|
|
5
|
+
* with `x / a` the compiler hoists `1/a` out of the loop (WGSL allows the
|
|
6
|
+
* approximation) and the loop silently becomes an FMA — it measured 2.9
|
|
7
|
+
* TFLOP/s on an M3 vs 0.84 for a real divide. `x >= b > 0` from the first
|
|
8
|
+
* step, so the chain is bounded and never divides by zero.
|
|
6
9
|
* 64 ops (32 divides + 32 adds) per loop iteration, same MAC-as-2 convention
|
|
7
10
|
* as the multiply version, so throughput is directly comparable.
|
|
8
11
|
*/
|
|
9
|
-
export declare const flopsF32DivWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: f32 = 1.2 + f32(idx & 15u) * 0.05;\n let b: f32 = 0.5 + f32(idx & 7u) * 0.001;\n var x0: f32 = f32(idx & 255u) * 0.0001 + 0.01;\n var x1: f32 = f32(idx & 255u) * 0.0001 + 0.02;\n var x2: f32 = f32(idx & 255u) * 0.0001 + 0.03;\n var x3: f32 = f32(idx & 255u) * 0.0001 + 0.04;\n var x4: f32 = f32(idx & 255u) * 0.0001 + 0.05;\n var x5: f32 = f32(idx & 255u) * 0.0001 + 0.06;\n var x6: f32 = f32(idx & 255u) * 0.0001 + 0.07;\n var x7: f32 = f32(idx & 255u) * 0.0001 + 0.08;\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 =
|
|
12
|
+
export declare const flopsF32DivWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: f32 = 1.2 + f32(idx & 15u) * 0.05;\n let b: f32 = 0.5 + f32(idx & 7u) * 0.001;\n var x0: f32 = f32(idx & 255u) * 0.0001 + 0.01;\n var x1: f32 = f32(idx & 255u) * 0.0001 + 0.02;\n var x2: f32 = f32(idx & 255u) * 0.0001 + 0.03;\n var x3: f32 = f32(idx & 255u) * 0.0001 + 0.04;\n var x4: f32 = f32(idx & 255u) * 0.0001 + 0.05;\n var x5: f32 = f32(idx & 255u) * 0.0001 + 0.06;\n var x6: f32 = f32(idx & 255u) * 0.0001 + 0.07;\n var x7: f32 = f32(idx & 255u) * 0.0001 + 0.08;\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n }\n out[idx] = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;\n}\n";
|
|
10
13
|
//# sourceMappingURL=flopsF32Div.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF32Div.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF32Div.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF32Div.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF32Div.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,6nDA6D3B,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* fp32 divide-add FLOPS probe. Same shape as {@link flopsF32ScalarWgsl}
|
|
3
3
|
* (eight independent chains, unrolled 4x) but with the multiply replaced by
|
|
4
|
-
* a divide: `x =
|
|
5
|
-
*
|
|
4
|
+
* a divide: `x = a / x + b`. The *divisor* must be the loop-carried value:
|
|
5
|
+
* with `x / a` the compiler hoists `1/a` out of the loop (WGSL allows the
|
|
6
|
+
* approximation) and the loop silently becomes an FMA — it measured 2.9
|
|
7
|
+
* TFLOP/s on an M3 vs 0.84 for a real divide. `x >= b > 0` from the first
|
|
8
|
+
* step, so the chain is bounded and never divides by zero.
|
|
6
9
|
* 64 ops (32 divides + 32 adds) per loop iteration, same MAC-as-2 convention
|
|
7
10
|
* as the multiply version, so throughput is directly comparable.
|
|
8
11
|
*/
|
|
@@ -32,38 +35,38 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
32
35
|
var x6: f32 = f32(idx & 255u) * 0.0001 + 0.07;
|
|
33
36
|
var x7: f32 = f32(idx & 255u) * 0.0001 + 0.08;
|
|
34
37
|
for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {
|
|
35
|
-
x0 =
|
|
36
|
-
x1 =
|
|
37
|
-
x2 =
|
|
38
|
-
x3 =
|
|
39
|
-
x4 =
|
|
40
|
-
x5 =
|
|
41
|
-
x6 =
|
|
42
|
-
x7 =
|
|
43
|
-
x0 =
|
|
44
|
-
x1 =
|
|
45
|
-
x2 =
|
|
46
|
-
x3 =
|
|
47
|
-
x4 =
|
|
48
|
-
x5 =
|
|
49
|
-
x6 =
|
|
50
|
-
x7 =
|
|
51
|
-
x0 =
|
|
52
|
-
x1 =
|
|
53
|
-
x2 =
|
|
54
|
-
x3 =
|
|
55
|
-
x4 =
|
|
56
|
-
x5 =
|
|
57
|
-
x6 =
|
|
58
|
-
x7 =
|
|
59
|
-
x0 =
|
|
60
|
-
x1 =
|
|
61
|
-
x2 =
|
|
62
|
-
x3 =
|
|
63
|
-
x4 =
|
|
64
|
-
x5 =
|
|
65
|
-
x6 =
|
|
66
|
-
x7 =
|
|
38
|
+
x0 = a / x0 + b;
|
|
39
|
+
x1 = a / x1 + b;
|
|
40
|
+
x2 = a / x2 + b;
|
|
41
|
+
x3 = a / x3 + b;
|
|
42
|
+
x4 = a / x4 + b;
|
|
43
|
+
x5 = a / x5 + b;
|
|
44
|
+
x6 = a / x6 + b;
|
|
45
|
+
x7 = a / x7 + b;
|
|
46
|
+
x0 = a / x0 + b;
|
|
47
|
+
x1 = a / x1 + b;
|
|
48
|
+
x2 = a / x2 + b;
|
|
49
|
+
x3 = a / x3 + b;
|
|
50
|
+
x4 = a / x4 + b;
|
|
51
|
+
x5 = a / x5 + b;
|
|
52
|
+
x6 = a / x6 + b;
|
|
53
|
+
x7 = a / x7 + b;
|
|
54
|
+
x0 = a / x0 + b;
|
|
55
|
+
x1 = a / x1 + b;
|
|
56
|
+
x2 = a / x2 + b;
|
|
57
|
+
x3 = a / x3 + b;
|
|
58
|
+
x4 = a / x4 + b;
|
|
59
|
+
x5 = a / x5 + b;
|
|
60
|
+
x6 = a / x6 + b;
|
|
61
|
+
x7 = a / x7 + b;
|
|
62
|
+
x0 = a / x0 + b;
|
|
63
|
+
x1 = a / x1 + b;
|
|
64
|
+
x2 = a / x2 + b;
|
|
65
|
+
x3 = a / x3 + b;
|
|
66
|
+
x4 = a / x4 + b;
|
|
67
|
+
x5 = a / x5 + b;
|
|
68
|
+
x6 = a / x6 + b;
|
|
69
|
+
x7 = a / x7 + b;
|
|
67
70
|
}
|
|
68
71
|
out[idx] = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;
|
|
69
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF32Div.js","sourceRoot":"","sources":["../../src/shaders/flopsF32Div.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF32Div.js","sourceRoot":"","sources":["../../src/shaders/flopsF32Div.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DzC,CAAC"}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* `unpack2x16float` builtins (round each of a vec2<f32>'s lanes to fp16 and
|
|
4
4
|
* back) — these don't need the `shader-f16` device feature, unlike the
|
|
5
5
|
* flops-f16-* kernels which compute *in* f16. Eight independent vec2<f32>
|
|
6
|
-
*
|
|
7
|
-
* chain moving and bounded
|
|
8
|
-
*
|
|
6
|
+
* chains, unrolled 4x; each step packs, unpacks, then a vec2 FMA keeps the
|
|
7
|
+
* chain moving and bounded. Counted as 2 ops per lane (one f32 -> f16
|
|
8
|
+
* convert and one back; the FMA is not counted): 128 ops per loop iteration.
|
|
9
9
|
*/
|
|
10
10
|
export declare const flopsF32F16ConvertWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: vec2<f32> = vec2<f32>(0.97 + f32(idx & 15u) * 0.001);\n let b: vec2<f32> = vec2<f32>(0.5 + f32(idx & 7u) * 0.001);\n var x0: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.01);\n var x1: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.02);\n var x2: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.03);\n var x3: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.04);\n var x4: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.05);\n var x5: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.06);\n var x6: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.07);\n var x7: vec2<f32> = vec2<f32>(f32(idx & 255u) * 0.0001 + 0.08);\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = unpack2x16float(pack2x16float(x0)) * a + b;\n x1 = unpack2x16float(pack2x16float(x1)) * a + b;\n x2 = unpack2x16float(pack2x16float(x2)) * a + b;\n x3 = unpack2x16float(pack2x16float(x3)) * a + b;\n x4 = unpack2x16float(pack2x16float(x4)) * a + b;\n x5 = unpack2x16float(pack2x16float(x5)) * a + b;\n x6 = unpack2x16float(pack2x16float(x6)) * a + b;\n x7 = unpack2x16float(pack2x16float(x7)) * a + b;\n x0 = unpack2x16float(pack2x16float(x0)) * a + b;\n x1 = unpack2x16float(pack2x16float(x1)) * a + b;\n x2 = unpack2x16float(pack2x16float(x2)) * a + b;\n x3 = unpack2x16float(pack2x16float(x3)) * a + b;\n x4 = unpack2x16float(pack2x16float(x4)) * a + b;\n x5 = unpack2x16float(pack2x16float(x5)) * a + b;\n x6 = unpack2x16float(pack2x16float(x6)) * a + b;\n x7 = unpack2x16float(pack2x16float(x7)) * a + b;\n x0 = unpack2x16float(pack2x16float(x0)) * a + b;\n x1 = unpack2x16float(pack2x16float(x1)) * a + b;\n x2 = unpack2x16float(pack2x16float(x2)) * a + b;\n x3 = unpack2x16float(pack2x16float(x3)) * a + b;\n x4 = unpack2x16float(pack2x16float(x4)) * a + b;\n x5 = unpack2x16float(pack2x16float(x5)) * a + b;\n x6 = unpack2x16float(pack2x16float(x6)) * a + b;\n x7 = unpack2x16float(pack2x16float(x7)) * a + b;\n x0 = unpack2x16float(pack2x16float(x0)) * a + b;\n x1 = unpack2x16float(pack2x16float(x1)) * a + b;\n x2 = unpack2x16float(pack2x16float(x2)) * a + b;\n x3 = unpack2x16float(pack2x16float(x3)) * a + b;\n x4 = unpack2x16float(pack2x16float(x4)) * a + b;\n x5 = unpack2x16float(pack2x16float(x5)) * a + b;\n x6 = unpack2x16float(pack2x16float(x6)) * a + b;\n x7 = unpack2x16float(pack2x16float(x7)) * a + b;\n }\n let s0 = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;\n out[idx] = s0.x + s0.y;\n}\n";
|
|
11
11
|
//# sourceMappingURL=flopsF32F16Convert.d.ts.map
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* `unpack2x16float` builtins (round each of a vec2<f32>'s lanes to fp16 and
|
|
4
4
|
* back) — these don't need the `shader-f16` device feature, unlike the
|
|
5
5
|
* flops-f16-* kernels which compute *in* f16. Eight independent vec2<f32>
|
|
6
|
-
*
|
|
7
|
-
* chain moving and bounded
|
|
8
|
-
*
|
|
6
|
+
* chains, unrolled 4x; each step packs, unpacks, then a vec2 FMA keeps the
|
|
7
|
+
* chain moving and bounded. Counted as 2 ops per lane (one f32 -> f16
|
|
8
|
+
* convert and one back; the FMA is not counted): 128 ops per loop iteration.
|
|
9
9
|
*/
|
|
10
10
|
export const flopsF32F16ConvertWgsl = /* wgsl */ `
|
|
11
11
|
struct Params {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fp32 vec4 FLOPS probe:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* scalar
|
|
2
|
+
* fp32 vec4 FLOPS probe: eight independent FMA chains, each held in a
|
|
3
|
+
* `vec4<f32>` register, unrolled 4x — the same chain/unroll shape as
|
|
4
|
+
* {@link flopsF32ScalarWgsl} so the two are directly comparable. (A single
|
|
5
|
+
* vec4 chain measured FMA latency, not throughput: 4x slower than scalar on
|
|
6
|
+
* an M3 purely from the missing ILP.) On scalar-SIMT GPUs each vec4 FMA is 4
|
|
7
|
+
* scalar FMAs. 8 chains x 4 unrolled x 4 lanes = 128 FMAs (256 FLOPs) per
|
|
8
|
+
* loop iteration.
|
|
7
9
|
*/
|
|
8
|
-
export declare const flopsF32Vec4Wgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let s: f32 = f32(idx & 15u) * 0.001;\n let a: vec4<f32> = vec4<f32>(1.0 - s, 1.0 - 2.0 * s, 1.0 - 3.0 * s, 1.0 - 4.0 * s);\n let b: vec4<f32> = vec4<f32>(0.5 + s, 0.5 + 2.0 * s, 0.5 + 3.0 * s, 0.5 + 4.0 * s);\n var
|
|
10
|
+
export declare const flopsF32Vec4Wgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let s: f32 = f32(idx & 15u) * 0.001;\n let a: vec4<f32> = vec4<f32>(1.0 - s, 1.0 - 2.0 * s, 1.0 - 3.0 * s, 1.0 - 4.0 * s);\n let b: vec4<f32> = vec4<f32>(0.5 + s, 0.5 + 2.0 * s, 0.5 + 3.0 * s, 0.5 + 4.0 * s);\n var x0: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.01);\n var x1: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.02);\n var x2: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.03);\n var x3: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.04);\n var x4: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.05);\n var x5: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.06);\n var x6: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.07);\n var x7: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.08);\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n x0 = x0 * a + b;\n x1 = x1 * a + b;\n x2 = x2 * a + b;\n x3 = x3 * a + b;\n x4 = x4 * a + b;\n x5 = x5 * a + b;\n x6 = x6 * a + b;\n x7 = x7 * a + b;\n }\n let t = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;\n out[idx] = t.x + t.y + t.z + t.w;\n}\n";
|
|
9
11
|
//# sourceMappingURL=flopsF32Vec4.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF32Vec4.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF32Vec4.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF32Vec4.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsF32Vec4.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,m6DA+D5B,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fp32 vec4 FLOPS probe:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* scalar
|
|
2
|
+
* fp32 vec4 FLOPS probe: eight independent FMA chains, each held in a
|
|
3
|
+
* `vec4<f32>` register, unrolled 4x — the same chain/unroll shape as
|
|
4
|
+
* {@link flopsF32ScalarWgsl} so the two are directly comparable. (A single
|
|
5
|
+
* vec4 chain measured FMA latency, not throughput: 4x slower than scalar on
|
|
6
|
+
* an M3 purely from the missing ILP.) On scalar-SIMT GPUs each vec4 FMA is 4
|
|
7
|
+
* scalar FMAs. 8 chains x 4 unrolled x 4 lanes = 128 FMAs (256 FLOPs) per
|
|
8
|
+
* loop iteration.
|
|
7
9
|
*/
|
|
8
10
|
export const flopsF32Vec4Wgsl = /* wgsl */ `
|
|
9
11
|
struct Params {
|
|
@@ -23,11 +25,50 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
23
25
|
let s: f32 = f32(idx & 15u) * 0.001;
|
|
24
26
|
let a: vec4<f32> = vec4<f32>(1.0 - s, 1.0 - 2.0 * s, 1.0 - 3.0 * s, 1.0 - 4.0 * s);
|
|
25
27
|
let b: vec4<f32> = vec4<f32>(0.5 + s, 0.5 + 2.0 * s, 0.5 + 3.0 * s, 0.5 + 4.0 * s);
|
|
26
|
-
var
|
|
28
|
+
var x0: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.01);
|
|
29
|
+
var x1: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.02);
|
|
30
|
+
var x2: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.03);
|
|
31
|
+
var x3: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.04);
|
|
32
|
+
var x4: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.05);
|
|
33
|
+
var x5: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.06);
|
|
34
|
+
var x6: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.07);
|
|
35
|
+
var x7: vec4<f32> = vec4<f32>(f32(idx & 255u) * 0.0001 + 0.08);
|
|
27
36
|
for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {
|
|
28
|
-
|
|
37
|
+
x0 = x0 * a + b;
|
|
38
|
+
x1 = x1 * a + b;
|
|
39
|
+
x2 = x2 * a + b;
|
|
40
|
+
x3 = x3 * a + b;
|
|
41
|
+
x4 = x4 * a + b;
|
|
42
|
+
x5 = x5 * a + b;
|
|
43
|
+
x6 = x6 * a + b;
|
|
44
|
+
x7 = x7 * a + b;
|
|
45
|
+
x0 = x0 * a + b;
|
|
46
|
+
x1 = x1 * a + b;
|
|
47
|
+
x2 = x2 * a + b;
|
|
48
|
+
x3 = x3 * a + b;
|
|
49
|
+
x4 = x4 * a + b;
|
|
50
|
+
x5 = x5 * a + b;
|
|
51
|
+
x6 = x6 * a + b;
|
|
52
|
+
x7 = x7 * a + b;
|
|
53
|
+
x0 = x0 * a + b;
|
|
54
|
+
x1 = x1 * a + b;
|
|
55
|
+
x2 = x2 * a + b;
|
|
56
|
+
x3 = x3 * a + b;
|
|
57
|
+
x4 = x4 * a + b;
|
|
58
|
+
x5 = x5 * a + b;
|
|
59
|
+
x6 = x6 * a + b;
|
|
60
|
+
x7 = x7 * a + b;
|
|
61
|
+
x0 = x0 * a + b;
|
|
62
|
+
x1 = x1 * a + b;
|
|
63
|
+
x2 = x2 * a + b;
|
|
64
|
+
x3 = x3 * a + b;
|
|
65
|
+
x4 = x4 * a + b;
|
|
66
|
+
x5 = x5 * a + b;
|
|
67
|
+
x6 = x6 * a + b;
|
|
68
|
+
x7 = x7 * a + b;
|
|
29
69
|
}
|
|
30
|
-
|
|
70
|
+
let t = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7;
|
|
71
|
+
out[idx] = t.x + t.y + t.z + t.w;
|
|
31
72
|
}
|
|
32
73
|
`;
|
|
33
74
|
//# sourceMappingURL=flopsF32Vec4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsF32Vec4.js","sourceRoot":"","sources":["../../src/shaders/flopsF32Vec4.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsF32Vec4.js","sourceRoot":"","sources":["../../src/shaders/flopsF32Vec4.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+D1C,CAAC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* i32 divide-add ops probe. Same shape as {@link flopsI8ScalarWgsl} (eight
|
|
3
3
|
* independent chains, unrolled 4x) but with the multiply replaced by integer
|
|
4
|
-
* division: `x =
|
|
5
|
-
*
|
|
4
|
+
* division: `x = a / x + b`. The divisor is the loop-carried value so the
|
|
5
|
+
* division can't be strength-reduced against a loop-invariant `a` (see
|
|
6
|
+
* flopsF32Div.ts). `x >= b >= 5` from the first step, so it never divides by
|
|
7
|
+
* zero and stays within `[b, a / b + b]`. 64 ops (32 divides + 32
|
|
6
8
|
* adds) per loop iteration, same MAC-as-2 convention as the other scalar
|
|
7
9
|
* probes.
|
|
8
10
|
*/
|
|
9
|
-
export declare const flopsI32DivWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: i32 =
|
|
11
|
+
export declare const flopsI32DivWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: i32 = 100003 + i32(idx & 255u) * 7;\n let b: i32 = 5 + i32(idx & 7u);\n var x0: i32 = i32(idx & 255u) + 1000;\n var x1: i32 = i32(idx & 255u) + 2000;\n var x2: i32 = i32(idx & 255u) + 3000;\n var x3: i32 = i32(idx & 255u) + 4000;\n var x4: i32 = i32(idx & 255u) + 5000;\n var x5: i32 = i32(idx & 255u) + 6000;\n var x6: i32 = i32(idx & 255u) + 7000;\n var x7: i32 = i32(idx & 255u) + 8000;\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n x0 = a / x0 + b;\n x1 = a / x1 + b;\n x2 = a / x2 + b;\n x3 = a / x3 + b;\n x4 = a / x4 + b;\n x5 = a / x5 + b;\n x6 = a / x6 + b;\n x7 = a / x7 + b;\n }\n out[idx] = f32(x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7);\n}\n";
|
|
10
12
|
//# sourceMappingURL=flopsI32Div.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsI32Div.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsI32Div.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsI32Div.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsI32Div.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,ijDA6D3B,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* i32 divide-add ops probe. Same shape as {@link flopsI8ScalarWgsl} (eight
|
|
3
3
|
* independent chains, unrolled 4x) but with the multiply replaced by integer
|
|
4
|
-
* division: `x =
|
|
5
|
-
*
|
|
4
|
+
* division: `x = a / x + b`. The divisor is the loop-carried value so the
|
|
5
|
+
* division can't be strength-reduced against a loop-invariant `a` (see
|
|
6
|
+
* flopsF32Div.ts). `x >= b >= 5` from the first step, so it never divides by
|
|
7
|
+
* zero and stays within `[b, a / b + b]`. 64 ops (32 divides + 32
|
|
6
8
|
* adds) per loop iteration, same MAC-as-2 convention as the other scalar
|
|
7
9
|
* probes.
|
|
8
10
|
*/
|
|
@@ -21,7 +23,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
21
23
|
if (idx >= params.threads) {
|
|
22
24
|
return;
|
|
23
25
|
}
|
|
24
|
-
let a: i32 =
|
|
26
|
+
let a: i32 = 100003 + i32(idx & 255u) * 7;
|
|
25
27
|
let b: i32 = 5 + i32(idx & 7u);
|
|
26
28
|
var x0: i32 = i32(idx & 255u) + 1000;
|
|
27
29
|
var x1: i32 = i32(idx & 255u) + 2000;
|
|
@@ -32,38 +34,38 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
|
32
34
|
var x6: i32 = i32(idx & 255u) + 7000;
|
|
33
35
|
var x7: i32 = i32(idx & 255u) + 8000;
|
|
34
36
|
for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {
|
|
35
|
-
x0 =
|
|
36
|
-
x1 =
|
|
37
|
-
x2 =
|
|
38
|
-
x3 =
|
|
39
|
-
x4 =
|
|
40
|
-
x5 =
|
|
41
|
-
x6 =
|
|
42
|
-
x7 =
|
|
43
|
-
x0 =
|
|
44
|
-
x1 =
|
|
45
|
-
x2 =
|
|
46
|
-
x3 =
|
|
47
|
-
x4 =
|
|
48
|
-
x5 =
|
|
49
|
-
x6 =
|
|
50
|
-
x7 =
|
|
51
|
-
x0 =
|
|
52
|
-
x1 =
|
|
53
|
-
x2 =
|
|
54
|
-
x3 =
|
|
55
|
-
x4 =
|
|
56
|
-
x5 =
|
|
57
|
-
x6 =
|
|
58
|
-
x7 =
|
|
59
|
-
x0 =
|
|
60
|
-
x1 =
|
|
61
|
-
x2 =
|
|
62
|
-
x3 =
|
|
63
|
-
x4 =
|
|
64
|
-
x5 =
|
|
65
|
-
x6 =
|
|
66
|
-
x7 =
|
|
37
|
+
x0 = a / x0 + b;
|
|
38
|
+
x1 = a / x1 + b;
|
|
39
|
+
x2 = a / x2 + b;
|
|
40
|
+
x3 = a / x3 + b;
|
|
41
|
+
x4 = a / x4 + b;
|
|
42
|
+
x5 = a / x5 + b;
|
|
43
|
+
x6 = a / x6 + b;
|
|
44
|
+
x7 = a / x7 + b;
|
|
45
|
+
x0 = a / x0 + b;
|
|
46
|
+
x1 = a / x1 + b;
|
|
47
|
+
x2 = a / x2 + b;
|
|
48
|
+
x3 = a / x3 + b;
|
|
49
|
+
x4 = a / x4 + b;
|
|
50
|
+
x5 = a / x5 + b;
|
|
51
|
+
x6 = a / x6 + b;
|
|
52
|
+
x7 = a / x7 + b;
|
|
53
|
+
x0 = a / x0 + b;
|
|
54
|
+
x1 = a / x1 + b;
|
|
55
|
+
x2 = a / x2 + b;
|
|
56
|
+
x3 = a / x3 + b;
|
|
57
|
+
x4 = a / x4 + b;
|
|
58
|
+
x5 = a / x5 + b;
|
|
59
|
+
x6 = a / x6 + b;
|
|
60
|
+
x7 = a / x7 + b;
|
|
61
|
+
x0 = a / x0 + b;
|
|
62
|
+
x1 = a / x1 + b;
|
|
63
|
+
x2 = a / x2 + b;
|
|
64
|
+
x3 = a / x3 + b;
|
|
65
|
+
x4 = a / x4 + b;
|
|
66
|
+
x5 = a / x5 + b;
|
|
67
|
+
x6 = a / x6 + b;
|
|
68
|
+
x7 = a / x7 + b;
|
|
67
69
|
}
|
|
68
70
|
out[idx] = f32(x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7);
|
|
69
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsI32Div.js","sourceRoot":"","sources":["../../src/shaders/flopsI32Div.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsI32Div.js","sourceRoot":"","sources":["../../src/shaders/flopsI32Div.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DzC,CAAC"}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* but each step is `xf = f32(xi) * a + b; xi = i32(xf)`: two conversions
|
|
4
4
|
* plus the same FMA as the fp32 scalar test, so the delta against that test
|
|
5
5
|
* isolates conversion cost. `a` < 1 keeps the round-tripped integer bounded.
|
|
6
|
-
*
|
|
7
|
-
* iteration.
|
|
6
|
+
* Counted as 2 ops per lane step (one convert each way; the FMA is not
|
|
7
|
+
* counted): 64 ops per loop iteration.
|
|
8
8
|
*/
|
|
9
9
|
export declare const flopsI32F32ConvertWgsl = "\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let a: f32 = 0.9 + f32(idx & 15u) * 0.005;\n let b: f32 = 3.0 + f32(idx & 7u) * 0.1;\n var x0: i32 = i32(idx & 255u) + 100;\n var x1: i32 = i32(idx & 255u) + 200;\n var x2: i32 = i32(idx & 255u) + 300;\n var x3: i32 = i32(idx & 255u) + 400;\n var x4: i32 = i32(idx & 255u) + 500;\n var x5: i32 = i32(idx & 255u) + 600;\n var x6: i32 = i32(idx & 255u) + 700;\n var x7: i32 = i32(idx & 255u) + 800;\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n x0 = i32(f32(x0) * a + b);\n x1 = i32(f32(x1) * a + b);\n x2 = i32(f32(x2) * a + b);\n x3 = i32(f32(x3) * a + b);\n x4 = i32(f32(x4) * a + b);\n x5 = i32(f32(x5) * a + b);\n x6 = i32(f32(x6) * a + b);\n x7 = i32(f32(x7) * a + b);\n x0 = i32(f32(x0) * a + b);\n x1 = i32(f32(x1) * a + b);\n x2 = i32(f32(x2) * a + b);\n x3 = i32(f32(x3) * a + b);\n x4 = i32(f32(x4) * a + b);\n x5 = i32(f32(x5) * a + b);\n x6 = i32(f32(x6) * a + b);\n x7 = i32(f32(x7) * a + b);\n x0 = i32(f32(x0) * a + b);\n x1 = i32(f32(x1) * a + b);\n x2 = i32(f32(x2) * a + b);\n x3 = i32(f32(x3) * a + b);\n x4 = i32(f32(x4) * a + b);\n x5 = i32(f32(x5) * a + b);\n x6 = i32(f32(x6) * a + b);\n x7 = i32(f32(x7) * a + b);\n x0 = i32(f32(x0) * a + b);\n x1 = i32(f32(x1) * a + b);\n x2 = i32(f32(x2) * a + b);\n x3 = i32(f32(x3) * a + b);\n x4 = i32(f32(x4) * a + b);\n x5 = i32(f32(x5) * a + b);\n x6 = i32(f32(x6) * a + b);\n x7 = i32(f32(x7) * a + b);\n }\n out[idx] = f32(x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7);\n}\n";
|
|
10
10
|
//# sourceMappingURL=flopsI32F32Convert.d.ts.map
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* but each step is `xf = f32(xi) * a + b; xi = i32(xf)`: two conversions
|
|
4
4
|
* plus the same FMA as the fp32 scalar test, so the delta against that test
|
|
5
5
|
* isolates conversion cost. `a` < 1 keeps the round-tripped integer bounded.
|
|
6
|
-
*
|
|
7
|
-
* iteration.
|
|
6
|
+
* Counted as 2 ops per lane step (one convert each way; the FMA is not
|
|
7
|
+
* counted): 64 ops per loop iteration.
|
|
8
8
|
*/
|
|
9
9
|
export const flopsI32F32ConvertWgsl = /* wgsl */ `
|
|
10
10
|
struct Params {
|
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
* int8 packed-dot-product FLOPS probe: uses the `packed_4x8_integer_dot_product`
|
|
3
3
|
* extension's `dot4I8Packed` builtin directly (two u32s, each four packed
|
|
4
4
|
* signed int8 lanes, one instruction) in a tight accumulation loop, to
|
|
5
|
-
* isolate the instruction's peak throughput.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* isolate the instruction's peak throughput. Eight independent accumulators
|
|
6
|
+
* per thread so the number is throughput, not the latency of one dependent
|
|
7
|
+
* chain. Each `a` is fed back from its own running accumulator every
|
|
8
|
+
* iteration (not just `idx`-derived and fixed), so `dot4I8Packed(a, b)` is
|
|
9
|
+
* genuinely loop-carried — a compiler that
|
|
8
10
|
* noticed `a`/`b` were loop-invariant could otherwise hoist the call out of
|
|
9
11
|
* the loop and replace all `iterations` of it with one call + a multiply,
|
|
10
12
|
* which is exactly what happened before this fix (the loop collapsed to
|
|
11
13
|
* ~free, and the dispatch finished faster than the timestamp-query clock's
|
|
12
|
-
* resolution, reading back as a literal 0ns elapsed).
|
|
14
|
+
* resolution, reading back as a literal 0ns elapsed). 8 dots x 4 MACs =
|
|
15
|
+
* 64 ops per loop iteration.
|
|
13
16
|
*
|
|
14
17
|
* `packed_4x8_integer_dot_product` is a WGSL *language extension* (gated by
|
|
15
18
|
* `navigator.gpu.wgslLanguageFeatures`, checked as `ctx.info.supportsI8Dot`
|
|
@@ -19,5 +22,5 @@
|
|
|
19
22
|
* 'f16', or 'primitive_index'" — the compiler listing valid enable-extension
|
|
20
23
|
* names), which used to go undetected and read back as a silent 0ns result.
|
|
21
24
|
*/
|
|
22
|
-
export declare const flopsI8Dp4aWgsl = "\nrequires packed_4x8_integer_dot_product;\n\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let b: u32 = 0x05060708u ^ (idx * 0x85ebca6bu);\n var
|
|
25
|
+
export declare const flopsI8Dp4aWgsl = "\nrequires packed_4x8_integer_dot_product;\n\nstruct Params {\n threads: u32,\n iterations: u32,\n};\n\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read_write> out: array<f32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let idx = gid.x;\n if (idx >= params.threads) {\n return;\n }\n let b: u32 = 0x05060708u ^ (idx * 0x85ebca6bu);\n var a0: u32 = 0x01020300u ^ (idx * 0x9e3779b1u);\n var acc0: i32 = i32(idx & 255u) + 0;\n var a1: u32 = 0x01020301u ^ (idx * 0x9e3779b1u);\n var acc1: i32 = i32(idx & 255u) + 1;\n var a2: u32 = 0x01020302u ^ (idx * 0x9e3779b1u);\n var acc2: i32 = i32(idx & 255u) + 2;\n var a3: u32 = 0x01020303u ^ (idx * 0x9e3779b1u);\n var acc3: i32 = i32(idx & 255u) + 3;\n var a4: u32 = 0x01020304u ^ (idx * 0x9e3779b1u);\n var acc4: i32 = i32(idx & 255u) + 4;\n var a5: u32 = 0x01020305u ^ (idx * 0x9e3779b1u);\n var acc5: i32 = i32(idx & 255u) + 5;\n var a6: u32 = 0x01020306u ^ (idx * 0x9e3779b1u);\n var acc6: i32 = i32(idx & 255u) + 6;\n var a7: u32 = 0x01020307u ^ (idx * 0x9e3779b1u);\n var acc7: i32 = i32(idx & 255u) + 7;\n for (var i: u32 = 0u; i < params.iterations; i = i + 1u) {\n acc0 = acc0 + dot4I8Packed(a0, b);\n a0 = a0 ^ u32(acc0);\n acc1 = acc1 + dot4I8Packed(a1, b);\n a1 = a1 ^ u32(acc1);\n acc2 = acc2 + dot4I8Packed(a2, b);\n a2 = a2 ^ u32(acc2);\n acc3 = acc3 + dot4I8Packed(a3, b);\n a3 = a3 ^ u32(acc3);\n acc4 = acc4 + dot4I8Packed(a4, b);\n a4 = a4 ^ u32(acc4);\n acc5 = acc5 + dot4I8Packed(a5, b);\n a5 = a5 ^ u32(acc5);\n acc6 = acc6 + dot4I8Packed(a6, b);\n a6 = a6 ^ u32(acc6);\n acc7 = acc7 + dot4I8Packed(a7, b);\n a7 = a7 ^ u32(acc7);\n }\n out[idx] = f32(acc0 + acc1 + acc2 + acc3 + acc4 + acc5 + acc6 + acc7);\n}\n";
|
|
23
26
|
//# sourceMappingURL=flopsI8Dp4a.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flopsI8Dp4a.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsI8Dp4a.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flopsI8Dp4a.d.ts","sourceRoot":"","sources":["../../src/shaders/flopsI8Dp4a.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,eAAe,uzDAsD3B,CAAC"}
|