usearch 2.26.1 → 2.26.3
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 +1 -1
- package/include/usearch/index.hpp +5 -1
- package/numkong/CITATION.cff +13 -9
- package/numkong/CONTRIBUTING.md +29 -24
- package/numkong/Cargo.toml +1 -1
- package/numkong/README.md +21 -7
- package/numkong/binding.gyp +47 -31
- package/numkong/build.rs +15 -5
- package/numkong/c/dispatch.h +0 -1
- package/numkong/c/parallel.c +139 -0
- package/numkong/c/parallel.h +47 -0
- package/numkong/cmake/toolchain-wasi.cmake +39 -5
- package/numkong/include/README.md +24 -17
- package/numkong/include/numkong/attention/sapphireamx.h +6 -6
- package/numkong/include/numkong/attention/sme.h +2 -2
- package/numkong/include/numkong/capabilities.h +2 -2
- package/numkong/include/numkong/cast/README.md +9 -7
- package/numkong/include/numkong/cast/loongsonasx.h +48 -40
- package/numkong/include/numkong/cast/serial.h +89 -11
- package/numkong/include/numkong/cast.h +3 -3
- package/numkong/include/numkong/curved/README.md +10 -10
- package/numkong/include/numkong/curved/neon.h +1 -0
- package/numkong/include/numkong/curved/neonbfdot.h +1 -0
- package/numkong/include/numkong/curved/smef64.h +1 -0
- package/numkong/include/numkong/dot/README.md +18 -18
- package/numkong/include/numkong/dot/alder.h +8 -8
- package/numkong/include/numkong/dot/haswell.h +8 -8
- package/numkong/include/numkong/dot/icelake.h +12 -12
- package/numkong/include/numkong/dot/loongsonasx.h +6 -6
- package/numkong/include/numkong/dot/neon.h +2 -1
- package/numkong/include/numkong/dot/neonbfdot.h +1 -0
- package/numkong/include/numkong/dot/neonfhm.h +1 -0
- package/numkong/include/numkong/dot/neonsdot.h +1 -0
- package/numkong/include/numkong/dot/powervsx.h +3 -3
- package/numkong/include/numkong/dot/serial.h +19 -6
- package/numkong/include/numkong/dot/skylake.h +4 -4
- package/numkong/include/numkong/dot/svehalf.h +1 -1
- package/numkong/include/numkong/dot/v128relaxed.h +24 -23
- package/numkong/include/numkong/dots/README.md +26 -26
- package/numkong/include/numkong/dots/genoa.h +3 -1
- package/numkong/include/numkong/dots/icelake.h +1 -0
- package/numkong/include/numkong/dots/powervsx.h +1 -1
- package/numkong/include/numkong/dots/serial.h +32 -33
- package/numkong/include/numkong/dots/sierra.h +4 -3
- package/numkong/include/numkong/each/README.md +5 -3
- package/numkong/include/numkong/each/sapphire.h +2 -0
- package/numkong/include/numkong/each/skylake.h +1 -0
- package/numkong/include/numkong/geospatial/README.md +6 -6
- package/numkong/include/numkong/geospatial/v128relaxed.h +1 -0
- package/numkong/include/numkong/maxsim/README.md +5 -5
- package/numkong/include/numkong/maxsim/genoa.h +4 -0
- package/numkong/include/numkong/maxsim/icelake.h +1 -0
- package/numkong/include/numkong/maxsim/serial.h +22 -9
- package/numkong/include/numkong/maxsim/sme.h +3 -2
- package/numkong/include/numkong/mesh/README.md +7 -4
- package/numkong/include/numkong/mesh/genoa.h +2 -2
- package/numkong/include/numkong/mesh/haswell.h +8 -8
- package/numkong/include/numkong/mesh/neon.h +6 -6
- package/numkong/include/numkong/mesh/neonbfdot.h +3 -2
- package/numkong/include/numkong/mesh/neonfhm.h +3 -2
- package/numkong/include/numkong/mesh/rvv.h +4 -4
- package/numkong/include/numkong/mesh/serial.h +17 -17
- package/numkong/include/numkong/mesh/skylake.h +4 -4
- package/numkong/include/numkong/mesh/v128relaxed.h +4 -4
- package/numkong/include/numkong/mesh.hpp +2 -2
- package/numkong/include/numkong/numkong.h +1 -1
- package/numkong/include/numkong/numkong.hpp +1 -1
- package/numkong/include/numkong/probability/README.md +17 -15
- package/numkong/include/numkong/probability/skylake.h +1 -1
- package/numkong/include/numkong/reduce/README.md +27 -21
- package/numkong/include/numkong/reduce/genoa.h +2 -1
- package/numkong/include/numkong/reduce/icelake.h +1 -0
- package/numkong/include/numkong/reduce/neon.h +1 -1
- package/numkong/include/numkong/reduce/serial.h +9 -9
- package/numkong/include/numkong/reduce/skylake.h +4 -4
- package/numkong/include/numkong/reduce.hpp +38 -0
- package/numkong/include/numkong/scalar/README.md +29 -28
- package/numkong/include/numkong/set/README.md +17 -14
- package/numkong/include/numkong/set/haswell.h +15 -16
- package/numkong/include/numkong/set/icelake.h +15 -16
- package/numkong/include/numkong/set/loongsonasx.h +12 -10
- package/numkong/include/numkong/set/neon.h +15 -19
- package/numkong/include/numkong/set/powervsx.h +15 -21
- package/numkong/include/numkong/set/serial.h +19 -20
- package/numkong/include/numkong/set/v128relaxed.h +10 -8
- package/numkong/include/numkong/sets/icelake.h +1 -0
- package/numkong/include/numkong/sparse/README.md +4 -4
- package/numkong/include/numkong/sparse/icelake.h +1 -0
- package/numkong/include/numkong/sparse/neon.h +1 -0
- package/numkong/include/numkong/sparse/serial.h +10 -3
- package/numkong/include/numkong/sparse/turin.h +1 -0
- package/numkong/include/numkong/spatial/README.md +25 -24
- package/numkong/include/numkong/spatial/alder.h +2 -1
- package/numkong/include/numkong/spatial/haswell.h +48 -40
- package/numkong/include/numkong/spatial/icelake.h +2 -1
- package/numkong/include/numkong/spatial/neon.h +54 -46
- package/numkong/include/numkong/spatial/neonbfdot.h +1 -1
- package/numkong/include/numkong/spatial/powervsx.h +54 -46
- package/numkong/include/numkong/spatial/serial.h +56 -46
- package/numkong/include/numkong/spatial/sierra.h +4 -3
- package/numkong/include/numkong/spatial/skylake.h +27 -22
- package/numkong/include/numkong/spatial/sve.h +6 -6
- package/numkong/include/numkong/spatial/svebfdot.h +1 -1
- package/numkong/include/numkong/spatial/svehalf.h +1 -1
- package/numkong/include/numkong/spatial/v128relaxed.h +36 -30
- package/numkong/include/numkong/spatials/README.md +15 -15
- package/numkong/include/numkong/spatials/genoa.h +3 -0
- package/numkong/include/numkong/spatials/graniteamx.h +2 -0
- package/numkong/include/numkong/spatials/icelake.h +1 -0
- package/numkong/include/numkong/spatials/sierra.h +1 -0
- package/numkong/include/numkong/tensor.hpp +236 -123
- package/numkong/include/numkong/trigonometry/README.md +4 -4
- package/numkong/include/numkong/trigonometry/serial.h +6 -6
- package/numkong/include/numkong/trigonometry/v128relaxed.h +1 -0
- package/numkong/include/numkong/types.hpp +46 -16
- package/numkong/include/numkong/vector.hpp +116 -23
- package/numkong/javascript/@numkong-darwin-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-darwin-x64/package.json +1 -1
- package/numkong/javascript/@numkong-linux-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-linux-x64/package.json +1 -1
- package/numkong/javascript/@numkong-win32-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-win32-x64/package.json +1 -1
- package/numkong/javascript/README.md +18 -16
- package/numkong/javascript/numkong.c +70 -40
- package/numkong/package.json +8 -8
- package/numkong/rust/README.md +19 -9
- package/numkong/rust/cast.rs +52 -1
- package/numkong/rust/each.rs +480 -7
- package/numkong/rust/matrix.rs +877 -216
- package/numkong/rust/numkong.rs +12 -8
- package/numkong/rust/reduce.rs +433 -5
- package/numkong/rust/tensor.rs +450 -842
- package/numkong/rust/vector.rs +520 -101
- package/numkong/swift/README.md +5 -3
- package/numkong/test/README.md +4 -4
- package/numkong/test/test-wasi.mjs +17 -0
- package/numkong/test/test_each.cpp +30 -1
- package/numkong/test/test_each.py +74 -1
- package/numkong/test/test_reduce.cpp +51 -0
- package/numkong/test/test_tensor.cpp +2 -63
- package/numkong/test/test_tensor.py +93 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/prebuilds/win32-x64/usearch.node +0 -0
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* - `f16` & `bf16` ↔ `f32` - often used for half-precision dot-products on older CPUs,
|
|
12
12
|
*
|
|
13
13
|
* Unlike most operation classes in NumKong, these are dependent on two input types: "from" & "to".
|
|
14
|
-
* It contains scalar helpers named like `
|
|
15
|
-
* `memcpy`-like vectorized operations, such as `
|
|
16
|
-
* `
|
|
14
|
+
* It contains scalar helpers named like `nk_f16_to_f32_serial` as well as buffer-to-buffer
|
|
15
|
+
* `memcpy`-like vectorized operations, such as `nk_cast` with `nk_cast_serial`,
|
|
16
|
+
* `nk_cast_neon`, `nk_cast_skylake`, and other platform-specific variants.
|
|
17
17
|
*
|
|
18
18
|
* It also includes "partial load" and "partial store" type-punned helper functions for handling
|
|
19
19
|
* IO between memory and registers, that are extensively reused in reductions, elementwise ops, and
|
|
@@ -42,19 +42,19 @@ def bilinear_complex(a: np.ndarray, b: np.ndarray, C: np.ndarray) -> complex:
|
|
|
42
42
|
|
|
43
43
|
Real bilinear and Mahalanobis:
|
|
44
44
|
|
|
45
|
-
| Input Type | Output Type | Description
|
|
46
|
-
| ---------- | ----------- |
|
|
47
|
-
| `f64` | `f64` | 64-bit IEEE 754 double precision
|
|
48
|
-
| `f32` | `
|
|
49
|
-
| `f16` | `f32` | 16-bit IEEE 754 half precision, widened output
|
|
50
|
-
| `bf16` | `f32` | 16-bit brain float, widened output
|
|
45
|
+
| Input Type | Output Type | Description |
|
|
46
|
+
| ---------- | ----------- | ------------------------------------------------ |
|
|
47
|
+
| `f64` | `f64` | 64-bit IEEE 754 double precision |
|
|
48
|
+
| `f32` | `f64` | 32-bit IEEE 754 single precision, widened output |
|
|
49
|
+
| `f16` | `f32` | 16-bit IEEE 754 half precision, widened output |
|
|
50
|
+
| `bf16` | `f32` | 16-bit brain float, widened output |
|
|
51
51
|
|
|
52
52
|
Complex bilinear:
|
|
53
53
|
|
|
54
54
|
| Input Type | Output Type | Description |
|
|
55
55
|
| ---------- | ----------- | ------------------------------------------ |
|
|
56
56
|
| `f64c` | `f64c` | 64-bit complex pairs |
|
|
57
|
-
| `f32c` | `
|
|
57
|
+
| `f32c` | `f64c` | 32-bit complex pairs, widened output |
|
|
58
58
|
| `f16c` | `f32c` | 16-bit complex pairs, widened output |
|
|
59
59
|
| `bf16c` | `f32c` | 16-bit brain complex pairs, widened output |
|
|
60
60
|
|
|
@@ -179,7 +179,7 @@ Measured with Wasmtime v42 (Cranelift backend).
|
|
|
179
179
|
| `nk_bilinear_bf16c_neonbfdot` | 5.05 gso/s, 17.0 ulp | 4.20 gso/s, 17.0 ulp | 4.04 gso/s, 17.0 ulp |
|
|
180
180
|
| __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
|
|
181
181
|
| `nk_bilinear_f16c_serial` | 2.81 gso/s, 51.8 ulp | 2.54 gso/s, 51.8 ulp | 2.48 gso/s, 51.8 ulp |
|
|
182
|
-
| `
|
|
182
|
+
| `nk_bilinear_f16c_neon` | 5.00 gso/s, 17.3 ulp | 4.16 gso/s, 17.3 ulp | 4.00 gso/s, 16.4 ulp |
|
|
183
183
|
| __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
|
|
184
184
|
| `nk_bilinear_f64_serial` | 0.717 gso/s, 0.4 ulp | 0.711 gso/s, 0.4 ulp | 0.721 gso/s, 0.4 ulp |
|
|
185
185
|
| `nk_mahalanobis_f64_serial` | 0.664 gso/s, 0.5 ulp | 0.667 gso/s, 0.5 ulp | 0.672 gso/s, 0.5 ulp |
|
|
@@ -196,8 +196,8 @@ Measured with Wasmtime v42 (Cranelift backend).
|
|
|
196
196
|
| __f16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
|
|
197
197
|
| `nk_bilinear_f16_serial` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
|
|
198
198
|
| `nk_mahalanobis_f16_serial` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
199
|
+
| `nk_bilinear_f16_neon` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
|
|
200
|
+
| `nk_mahalanobis_f16_neon` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
|
|
201
201
|
|
|
202
202
|
#### WASM
|
|
203
203
|
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
#include "numkong/types.h" // `nk_bf16_t`
|
|
31
31
|
#include "numkong/spatial/neon.h" // `nk_f32_sqrt_neon`
|
|
32
32
|
#include "numkong/cast/serial.h" // `nk_bf16_to_f32_serial`
|
|
33
|
+
#include "numkong/dot/serial.h" // `nk_dot_f16c_serial`, `nk_vdot_f16c_serial`
|
|
33
34
|
|
|
34
35
|
#if defined(__cplusplus)
|
|
35
36
|
extern "C" {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
#include "numkong/spatial/neon.h" // `nk_f64_sqrt_neon`
|
|
57
57
|
#include "numkong/dots/sme.h" // `nk_sme_zero_za64_tile_0_`
|
|
58
58
|
#include "numkong/curved/serial.h" // `nk_bilinear_f64_serial`
|
|
59
|
+
#include "numkong/dot/serial.h" // `nk_dot_f16c_serial`, `nk_vdot_f16c_serial`
|
|
59
60
|
|
|
60
61
|
#if defined(__cplusplus)
|
|
61
62
|
extern "C" {
|
|
@@ -46,28 +46,28 @@ def vdot_complex(a: List[number], b: List[number]) -> Tuple[number, number]:
|
|
|
46
46
|
|
|
47
47
|
Real and integer dot products:
|
|
48
48
|
|
|
49
|
-
| Input Type | Output Type | Description
|
|
50
|
-
| ---------- | ----------- |
|
|
51
|
-
| `f64` | `f64` | 64-bit IEEE 754 double precision
|
|
52
|
-
| `f32` | `
|
|
53
|
-
| `f16` | `f32` | 16-bit IEEE 754 half precision, widened output
|
|
54
|
-
| `bf16` | `f32` | 16-bit brain float, widened output
|
|
55
|
-
| `e4m3` | `f32` | 8-bit Float8: 4 exponent, 3 mantissa bits
|
|
56
|
-
| `e5m2` | `f32` | 8-bit Float8: 5 exponent, 2 mantissa bits
|
|
57
|
-
| `e2m3` | `f32` | 8-bit MX format: 2 exponent, 3 mantissa bits
|
|
58
|
-
| `e3m2` | `f32` | 8-bit MX format: 3 exponent, 2 mantissa bits
|
|
59
|
-
| `i8` | `i32` | 8-bit signed integers
|
|
60
|
-
| `u8` | `u32` | 8-bit unsigned integers
|
|
61
|
-
| `i4` | `i32` | 4-bit signed integers, packed nibble pairs
|
|
62
|
-
| `u4` | `u32` | 4-bit unsigned integers, packed nibble pairs
|
|
63
|
-
| `u1` | `u32` | 1-bit binary packed octets, popcount of AND
|
|
49
|
+
| Input Type | Output Type | Description |
|
|
50
|
+
| ---------- | ----------- | ------------------------------------------------ |
|
|
51
|
+
| `f64` | `f64` | 64-bit IEEE 754 double precision |
|
|
52
|
+
| `f32` | `f64` | 32-bit IEEE 754 single precision, widened output |
|
|
53
|
+
| `f16` | `f32` | 16-bit IEEE 754 half precision, widened output |
|
|
54
|
+
| `bf16` | `f32` | 16-bit brain float, widened output |
|
|
55
|
+
| `e4m3` | `f32` | 8-bit Float8: 4 exponent, 3 mantissa bits |
|
|
56
|
+
| `e5m2` | `f32` | 8-bit Float8: 5 exponent, 2 mantissa bits |
|
|
57
|
+
| `e2m3` | `f32` | 8-bit MX format: 2 exponent, 3 mantissa bits |
|
|
58
|
+
| `e3m2` | `f32` | 8-bit MX format: 3 exponent, 2 mantissa bits |
|
|
59
|
+
| `i8` | `i32` | 8-bit signed integers |
|
|
60
|
+
| `u8` | `u32` | 8-bit unsigned integers |
|
|
61
|
+
| `i4` | `i32` | 4-bit signed integers, packed nibble pairs |
|
|
62
|
+
| `u4` | `u32` | 4-bit unsigned integers, packed nibble pairs |
|
|
63
|
+
| `u1` | `u32` | 1-bit binary packed octets, popcount of AND |
|
|
64
64
|
|
|
65
65
|
Complex dot products (both `dot` and `vdot`):
|
|
66
66
|
|
|
67
67
|
| Input Type | Output Type | Description |
|
|
68
68
|
| ---------- | ----------- | ------------------------------------------ |
|
|
69
69
|
| `f64c` | `f64c` | 64-bit complex pairs |
|
|
70
|
-
| `f32c` | `
|
|
70
|
+
| `f32c` | `f64c` | 32-bit complex pairs, widened output |
|
|
71
71
|
| `f16c` | `f32c` | 16-bit complex pairs, widened output |
|
|
72
72
|
| `bf16c` | `f32c` | 16-bit brain complex pairs, widened output |
|
|
73
73
|
|
|
@@ -330,8 +330,8 @@ Measured with Wasmtime v42 (Cranelift backend).
|
|
|
330
330
|
| __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
|
|
331
331
|
| `nk_dot_f16c_serial` | 15.8 gb/s, 20.8 ulp | 13.0 gb/s, 64.1 ulp | 12.3 gb/s, 73.1 ulp |
|
|
332
332
|
| `nk_vdot_f16c_serial` | 15.8 gb/s, 24.8 ulp | 13.0 gb/s, 31.9 ulp | 12.3 gb/s, 137 ulp |
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
333
|
+
| `nk_dot_f16c_neon` | 26.1 gb/s, 3.0 ulp | 18.4 gb/s, 6.5 ulp | 16.8 gb/s, 20.5 ulp |
|
|
334
|
+
| `nk_vdot_f16c_neon` | 26.1 gb/s, 34.9 ulp | 18.5 gb/s, 40.7 ulp | 17.0 gb/s, 73.1 ulp |
|
|
335
335
|
| `nk_dot_f16c_neonfhm` | 25.3 gb/s, 3.0 ulp | 17.1 gb/s, 6.5 ulp | 15.9 gb/s, 20.5 ulp |
|
|
336
336
|
| `nk_vdot_f16c_neonfhm` | 25.0 gb/s, 31.4 ulp | 17.0 gb/s, 38.6 ulp | 15.8 gb/s, 67.6 ulp |
|
|
337
337
|
| __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
|
|
@@ -192,8 +192,8 @@ NK_INTERNAL void nk_dot_i8x32_finalize_alder(
|
|
|
192
192
|
nk_dot_i8x32_state_alder_t const *state_c, nk_dot_i8x32_state_alder_t const *state_d, //
|
|
193
193
|
nk_size_t total_dimensions, //
|
|
194
194
|
nk_i32_t a_sum, /* A row sum (unused for i8) */ //
|
|
195
|
-
nk_b128_vec_t
|
|
196
|
-
nk_b128_vec_t *
|
|
195
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × i32 B column sums */ //
|
|
196
|
+
nk_b128_vec_t *result_vec) {
|
|
197
197
|
nk_unused_(total_dimensions);
|
|
198
198
|
nk_unused_(a_sum);
|
|
199
199
|
|
|
@@ -217,8 +217,8 @@ NK_INTERNAL void nk_dot_i8x32_finalize_alder(
|
|
|
217
217
|
_mm_add_epi32(_mm_unpacklo_epi64(t_ab_high, t_cd_high), _mm_unpackhi_epi64(t_ab_high, t_cd_high)));
|
|
218
218
|
|
|
219
219
|
// Apply compensation: result = biased − 128 × Σb
|
|
220
|
-
__m128i correction_i32x4 = _mm_slli_epi32(
|
|
221
|
-
|
|
220
|
+
__m128i correction_i32x4 = _mm_slli_epi32(b_sums_vec->xmm, 7); // × 128
|
|
221
|
+
result_vec->xmm = _mm_sub_epi32(biased_i32x4, correction_i32x4);
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
NK_PUBLIC void nk_dot_u8_alder(nk_u8_t const *a_scalars, nk_u8_t const *b_scalars, nk_size_t count_scalars,
|
|
@@ -312,8 +312,8 @@ NK_INTERNAL void nk_dot_u8x32_finalize_alder(
|
|
|
312
312
|
nk_dot_u8x32_state_alder_t const *state_c, nk_dot_u8x32_state_alder_t const *state_d, //
|
|
313
313
|
nk_size_t total_dimensions, //
|
|
314
314
|
nk_i32_t a_sum, /* A row sum (unused for u8) */ //
|
|
315
|
-
nk_b128_vec_t
|
|
316
|
-
nk_b128_vec_t *
|
|
315
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × u32 B column sums */ //
|
|
316
|
+
nk_b128_vec_t *result_vec) {
|
|
317
317
|
nk_unused_(total_dimensions);
|
|
318
318
|
nk_unused_(a_sum);
|
|
319
319
|
|
|
@@ -337,8 +337,8 @@ NK_INTERNAL void nk_dot_u8x32_finalize_alder(
|
|
|
337
337
|
_mm_add_epi32(_mm_unpacklo_epi64(t_ab_high, t_cd_high), _mm_unpackhi_epi64(t_ab_high, t_cd_high)));
|
|
338
338
|
|
|
339
339
|
// Apply compensation: result = biased + 128 × Σb
|
|
340
|
-
__m128i correction_i32x4 = _mm_slli_epi32(
|
|
341
|
-
|
|
340
|
+
__m128i correction_i32x4 = _mm_slli_epi32(b_sums_vec->xmm, 7); // × 128
|
|
341
|
+
result_vec->xmm = _mm_add_epi32(biased_i32x4, correction_i32x4);
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
/**
|
|
@@ -895,7 +895,7 @@ nk_dot_e3m2_haswell_cycle:
|
|
|
895
895
|
|
|
896
896
|
/**
|
|
897
897
|
* @brief Internal helper state for dot-products of low-precision types, where 32-bit accumulation is enough.
|
|
898
|
-
* @sa nk_dot_f16x8_state_haswell_t,
|
|
898
|
+
* @sa nk_dot_f16x8_state_haswell_t, nk_dot_bf16x16_state_haswell_t
|
|
899
899
|
* @sa nk_dot_e4m3x16_state_haswell_t, nk_dot_e5m2x16_state_haswell_t
|
|
900
900
|
*/
|
|
901
901
|
typedef struct nk_dot_through_f32_state_haswell_t_ {
|
|
@@ -904,7 +904,7 @@ typedef struct nk_dot_through_f32_state_haswell_t_ {
|
|
|
904
904
|
|
|
905
905
|
/**
|
|
906
906
|
* @brief Initializes 32-bit accumulators for low-precision dot-products.
|
|
907
|
-
* @sa nk_dot_f16x8_init_haswell,
|
|
907
|
+
* @sa nk_dot_f16x8_init_haswell, nk_dot_bf16x16_init_haswell
|
|
908
908
|
* @sa nk_dot_e4m3x16_init_haswell, nk_dot_e5m2x16_init_haswell
|
|
909
909
|
*/
|
|
910
910
|
NK_INTERNAL void nk_dot_through_f32_init_haswell_(nk_dot_through_f32_state_haswell_t_ *state) {
|
|
@@ -913,7 +913,7 @@ NK_INTERNAL void nk_dot_through_f32_init_haswell_(nk_dot_through_f32_state_haswe
|
|
|
913
913
|
|
|
914
914
|
/**
|
|
915
915
|
* @brief Fuses 32-bit multiplication and accumulation for low-precision dot-products.
|
|
916
|
-
* @sa nk_dot_f16x8_update_haswell,
|
|
916
|
+
* @sa nk_dot_f16x8_update_haswell, nk_dot_bf16x16_update_haswell
|
|
917
917
|
* @sa nk_dot_e4m3x16_update_haswell, nk_dot_e5m2x16_update_haswell
|
|
918
918
|
*/
|
|
919
919
|
NK_INTERNAL void nk_dot_through_f32_update_haswell_(nk_dot_through_f32_state_haswell_t_ *state, nk_b256_vec_t a,
|
|
@@ -991,7 +991,7 @@ NK_INTERNAL void nk_dot_e4m3x32_update_haswell_(nk_dot_through_f32_state_haswell
|
|
|
991
991
|
|
|
992
992
|
/**
|
|
993
993
|
* @brief Finalizes 4x low-precision dot-products placing them into 4x consecutive 32-bit slots.
|
|
994
|
-
* @sa nk_dot_f16x8_finalize_haswell,
|
|
994
|
+
* @sa nk_dot_f16x8_finalize_haswell, nk_dot_bf16x16_finalize_haswell
|
|
995
995
|
* @sa nk_dot_e4m3x16_finalize_haswell, nk_dot_e5m2x16_finalize_haswell
|
|
996
996
|
*
|
|
997
997
|
* The goal of this kernel is simple - compute 4x horizontal reductions, each involving 8x floats.
|
|
@@ -1637,8 +1637,8 @@ NK_INTERNAL void nk_dot_i4x32_finalize_haswell(
|
|
|
1637
1637
|
nk_dot_i4x32_state_haswell_t const *state_c, nk_dot_i4x32_state_haswell_t const *state_d, //
|
|
1638
1638
|
nk_size_t total_dimensions, //
|
|
1639
1639
|
nk_i32_t a_sum, /* A row sum (signed sum of i4 values) */ //
|
|
1640
|
-
nk_b128_vec_t
|
|
1641
|
-
nk_b128_vec_t *
|
|
1640
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × i32 B column sums */ //
|
|
1641
|
+
nk_b128_vec_t *result_vec) {
|
|
1642
1642
|
|
|
1643
1643
|
// Compensated 4-way reduction with external correction sums.
|
|
1644
1644
|
// Formula: result = biased_product − 8×(Σa + Σb) − 64×depth_padded
|
|
@@ -1666,10 +1666,10 @@ NK_INTERNAL void nk_dot_i4x32_finalize_haswell(
|
|
|
1666
1666
|
|
|
1667
1667
|
// Apply compensation: result = biased − 8×(Σa + Σb) − 64×depth_padded
|
|
1668
1668
|
__m128i a_sum_broadcast_i32x4 = _mm_set1_epi32(a_sum);
|
|
1669
|
-
__m128i ab_sums_i32x4 = _mm_add_epi32(a_sum_broadcast_i32x4,
|
|
1669
|
+
__m128i ab_sums_i32x4 = _mm_add_epi32(a_sum_broadcast_i32x4, b_sums_vec->xmm);
|
|
1670
1670
|
__m128i correction_i32x4 = _mm_slli_epi32(ab_sums_i32x4, 3); // × 8
|
|
1671
1671
|
__m128i offset_i32x4 = _mm_set1_epi32((nk_i32_t)(-64LL * (nk_i64_t)depth_nibbles));
|
|
1672
|
-
|
|
1672
|
+
result_vec->xmm = _mm_add_epi32(_mm_sub_epi32(biased_i32x4, correction_i32x4), offset_i32x4);
|
|
1673
1673
|
}
|
|
1674
1674
|
|
|
1675
1675
|
/**
|
|
@@ -246,8 +246,8 @@ NK_INTERNAL void nk_dot_i8x64_finalize_icelake(
|
|
|
246
246
|
nk_dot_i8x64_state_icelake_t const *state_c, nk_dot_i8x64_state_icelake_t const *state_d, //
|
|
247
247
|
nk_size_t total_dimensions, //
|
|
248
248
|
nk_i32_t a_sum, /* A row sum (unused for i8) */ //
|
|
249
|
-
nk_b128_vec_t
|
|
250
|
-
nk_b128_vec_t *
|
|
249
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × i32 B column sums */ //
|
|
250
|
+
nk_b128_vec_t *result_vec) {
|
|
251
251
|
nk_unused_(total_dimensions);
|
|
252
252
|
nk_unused_(a_sum);
|
|
253
253
|
|
|
@@ -277,8 +277,8 @@ NK_INTERNAL void nk_dot_i8x64_finalize_icelake(
|
|
|
277
277
|
_mm_add_epi32(_mm_unpacklo_epi64(t_ab_high, t_cd_high), _mm_unpackhi_epi64(t_ab_high, t_cd_high)));
|
|
278
278
|
|
|
279
279
|
// Apply compensation: result = biased − 128 × Σb
|
|
280
|
-
__m128i correction_i32x4 = _mm_slli_epi32(
|
|
281
|
-
|
|
280
|
+
__m128i correction_i32x4 = _mm_slli_epi32(b_sums_vec->xmm, 7); // × 128
|
|
281
|
+
result_vec->xmm = _mm_sub_epi32(biased_i32x4, correction_i32x4);
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
typedef struct nk_dot_u8x64_state_icelake_t {
|
|
@@ -313,8 +313,8 @@ NK_INTERNAL void nk_dot_u8x64_finalize_icelake(
|
|
|
313
313
|
nk_dot_u8x64_state_icelake_t const *state_c, nk_dot_u8x64_state_icelake_t const *state_d, //
|
|
314
314
|
nk_size_t total_dimensions, //
|
|
315
315
|
nk_i32_t a_sum, /* A row sum (unused for u8) */ //
|
|
316
|
-
nk_b128_vec_t
|
|
317
|
-
nk_b128_vec_t *
|
|
316
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × u32 B column sums */ //
|
|
317
|
+
nk_b128_vec_t *result_vec) {
|
|
318
318
|
nk_unused_(total_dimensions);
|
|
319
319
|
nk_unused_(a_sum);
|
|
320
320
|
|
|
@@ -344,8 +344,8 @@ NK_INTERNAL void nk_dot_u8x64_finalize_icelake(
|
|
|
344
344
|
_mm_add_epi32(_mm_unpacklo_epi64(t_ab_high, t_cd_high), _mm_unpackhi_epi64(t_ab_high, t_cd_high)));
|
|
345
345
|
|
|
346
346
|
// Apply compensation: result = biased + 128 × Σb
|
|
347
|
-
__m128i correction_i32x4 = _mm_slli_epi32(
|
|
348
|
-
|
|
347
|
+
__m128i correction_i32x4 = _mm_slli_epi32(b_sums_vec->xmm, 7); // × 128
|
|
348
|
+
result_vec->xmm = _mm_add_epi32(biased_i32x4, correction_i32x4);
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
/**
|
|
@@ -568,8 +568,8 @@ NK_INTERNAL void nk_dot_i4x128_finalize_icelake(
|
|
|
568
568
|
nk_dot_i4x128_state_icelake_t const *state_c, nk_dot_i4x128_state_icelake_t const *state_d, //
|
|
569
569
|
nk_size_t total_dimensions, //
|
|
570
570
|
nk_i32_t a_sum, /* A row sum (signed sum of i4 values) */ //
|
|
571
|
-
nk_b128_vec_t
|
|
572
|
-
nk_b128_vec_t *
|
|
571
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × i32 B column sums */ //
|
|
572
|
+
nk_b128_vec_t *result_vec) {
|
|
573
573
|
|
|
574
574
|
// Compensated 4-way reduction with external correction sums.
|
|
575
575
|
// Formula: result = biased_product − 8×(Σa + Σb) − 64×depth_padded
|
|
@@ -606,10 +606,10 @@ NK_INTERNAL void nk_dot_i4x128_finalize_icelake(
|
|
|
606
606
|
|
|
607
607
|
// Apply compensation: result = biased − 8×(Σa + Σb) − 64×depth_padded
|
|
608
608
|
__m128i a_sum_broadcast_i32x4 = _mm_set1_epi32(a_sum);
|
|
609
|
-
__m128i ab_sums_i32x4 = _mm_add_epi32(a_sum_broadcast_i32x4,
|
|
609
|
+
__m128i ab_sums_i32x4 = _mm_add_epi32(a_sum_broadcast_i32x4, b_sums_vec->xmm);
|
|
610
610
|
__m128i correction_i32x4 = _mm_slli_epi32(ab_sums_i32x4, 3); // × 8
|
|
611
611
|
__m128i offset_i32x4 = _mm_set1_epi32((nk_i32_t)(-64LL * (nk_i64_t)depth_nibbles));
|
|
612
|
-
|
|
612
|
+
result_vec->xmm = _mm_add_epi32(_mm_sub_epi32(biased_i32x4, correction_i32x4), offset_i32x4);
|
|
613
613
|
}
|
|
614
614
|
|
|
615
615
|
typedef struct nk_dot_u4x128_state_icelake_t {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* @section dot_loongsonasx_stateful Stateful Streaming Logic
|
|
20
20
|
*
|
|
21
21
|
* - nk_dot_f64x4 state with Dot2 stable dot-products,
|
|
22
|
-
* -
|
|
22
|
+
* - nk_dot_f32x8 state with double-precision numerics,
|
|
23
23
|
* - nk_dot_through_i32 state for 8-bit signed and unsigned integer inputs.
|
|
24
24
|
*/
|
|
25
25
|
#ifndef NK_DOT_LOONGSONASX_H
|
|
@@ -348,7 +348,7 @@ NK_INTERNAL void nk_dot_f32x8_finalize_loongsonasx(
|
|
|
348
348
|
|
|
349
349
|
/**
|
|
350
350
|
* @brief Internal helper state for dot-products of integer types, where 32-bit accumulation is enough.
|
|
351
|
-
* @sa
|
|
351
|
+
* @sa nk_dot_i8x32_state_loongsonasx_t, nk_dot_u8x32_state_loongsonasx_t
|
|
352
352
|
*/
|
|
353
353
|
typedef struct nk_dot_through_i32_state_loongsonasx_t_ {
|
|
354
354
|
__m256i sum_i32x8;
|
|
@@ -356,7 +356,7 @@ typedef struct nk_dot_through_i32_state_loongsonasx_t_ {
|
|
|
356
356
|
|
|
357
357
|
/**
|
|
358
358
|
* @brief Initializes 32-bit accumulators for integer dot-products.
|
|
359
|
-
* @sa
|
|
359
|
+
* @sa nk_dot_i8x32_update_loongsonasx, nk_dot_u8x32_update_loongsonasx
|
|
360
360
|
*/
|
|
361
361
|
NK_INTERNAL void nk_dot_through_i32_init_loongsonasx_(nk_dot_through_i32_state_loongsonasx_t_ *state) {
|
|
362
362
|
state->sum_i32x8 = __lasx_xvreplgr2vr_w(0);
|
|
@@ -364,7 +364,7 @@ NK_INTERNAL void nk_dot_through_i32_init_loongsonasx_(nk_dot_through_i32_state_l
|
|
|
364
364
|
|
|
365
365
|
/**
|
|
366
366
|
* @brief Finalizes 4x integer dot-products placing them into 4x consecutive 32-bit slots.
|
|
367
|
-
* @sa
|
|
367
|
+
* @sa nk_dot_i8x32_update_loongsonasx, nk_dot_u8x32_update_loongsonasx
|
|
368
368
|
*/
|
|
369
369
|
NK_INTERNAL void nk_dot_through_i32_finalize_loongsonasx_( //
|
|
370
370
|
nk_dot_through_i32_state_loongsonasx_t_ const *state_a, nk_dot_through_i32_state_loongsonasx_t_ const *state_b, //
|
|
@@ -474,7 +474,7 @@ NK_INTERNAL void nk_dot_through_f32_init_loongsonasx_(nk_dot_through_f32_state_l
|
|
|
474
474
|
|
|
475
475
|
/**
|
|
476
476
|
* @brief Fuses 32-bit multiplication and accumulation for pre-converted f32 vectors.
|
|
477
|
-
* @sa
|
|
477
|
+
* @sa nk_dot_bf16x16_update_loongsonasx
|
|
478
478
|
*/
|
|
479
479
|
NK_INTERNAL void nk_dot_through_f32_update_loongsonasx_(nk_dot_through_f32_state_loongsonasx_t_ *state, nk_b256_vec_t a,
|
|
480
480
|
nk_b256_vec_t b, nk_size_t depth_offset,
|
|
@@ -486,7 +486,7 @@ NK_INTERNAL void nk_dot_through_f32_update_loongsonasx_(nk_dot_through_f32_state
|
|
|
486
486
|
|
|
487
487
|
/**
|
|
488
488
|
* @brief Finalizes 4x low-precision dot-products placing them into 4x consecutive 32-bit slots.
|
|
489
|
-
* @sa
|
|
489
|
+
* @sa nk_dot_bf16x16_finalize_loongsonasx
|
|
490
490
|
*
|
|
491
491
|
* Computes 4x horizontal reductions, each involving 8x floats, using LASX interleave instructions.
|
|
492
492
|
*/
|
|
@@ -89,7 +89,8 @@
|
|
|
89
89
|
#if NK_TARGET_ARM64_
|
|
90
90
|
#if NK_TARGET_NEON
|
|
91
91
|
|
|
92
|
-
#include "numkong/cast/neon.h"
|
|
92
|
+
#include "numkong/cast/neon.h" // `nk_e4m3x8_to_f16x8_neon_`
|
|
93
|
+
#include "numkong/dot/serial.h" // `nk_dot_f16c_serial`, `nk_vdot_f16c_serial`
|
|
93
94
|
|
|
94
95
|
#if defined(__cplusplus)
|
|
95
96
|
extern "C" {
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
#include "numkong/types.h"
|
|
64
64
|
#include "numkong/cast/serial.h" // `nk_partial_load_b8x8_serial_`
|
|
65
65
|
#include "numkong/cast/neon.h" // `nk_e4m3x8_to_bf16x8_neon_`
|
|
66
|
+
#include "numkong/dot/serial.h" // `nk_dot_bf16c_serial`, `nk_vdot_bf16c_serial`
|
|
66
67
|
|
|
67
68
|
#if defined(__cplusplus)
|
|
68
69
|
extern "C" {
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
#include "numkong/types.h"
|
|
66
66
|
#include "numkong/cast/serial.h" // `nk_partial_load_b8x8_serial_`
|
|
67
67
|
#include "numkong/cast/neon.h" // `nk_e4m3x8_to_f16x8_neon_`
|
|
68
|
+
#include "numkong/dot/serial.h" // `nk_dot_f16c_serial`, `nk_vdot_f16c_serial`
|
|
68
69
|
|
|
69
70
|
#if defined(__cplusplus)
|
|
70
71
|
extern "C" {
|
|
@@ -599,7 +599,7 @@ NK_INTERNAL void nk_dot_i8x16_finalize_powervsx(
|
|
|
599
599
|
nk_dot_i8x16_state_powervsx_t const *state_a, nk_dot_i8x16_state_powervsx_t const *state_b, //
|
|
600
600
|
nk_dot_i8x16_state_powervsx_t const *state_c, nk_dot_i8x16_state_powervsx_t const *state_d, //
|
|
601
601
|
nk_size_t total_dimensions, //
|
|
602
|
-
nk_i32_t a_sum, nk_b128_vec_t
|
|
602
|
+
nk_i32_t a_sum, nk_b128_vec_t const *b_sums_vec, nk_b128_vec_t *result_vec) {
|
|
603
603
|
nk_unused_(total_dimensions);
|
|
604
604
|
nk_unused_(a_sum);
|
|
605
605
|
|
|
@@ -624,8 +624,8 @@ NK_INTERNAL void nk_dot_i8x16_finalize_powervsx(
|
|
|
624
624
|
// Correction: VMSUMMBM(b, a⊕0x80) = Σ(b_i·(a_i+128)) = a·b + 128·Σb
|
|
625
625
|
// So a·b = biased − 128·Σb. B column sums are precomputed during packing.
|
|
626
626
|
nk_vu32x4_t shift_u32x4 = vec_splats((nk_u32_t)7);
|
|
627
|
-
nk_vi32x4_t correction_i32x4 = (nk_vi32x4_t)vec_sl((nk_vu32x4_t)
|
|
628
|
-
|
|
627
|
+
nk_vi32x4_t correction_i32x4 = (nk_vi32x4_t)vec_sl((nk_vu32x4_t)b_sums_vec->vi32x4, shift_u32x4);
|
|
628
|
+
result_vec->vi32x4 = vec_sub(biased_i32x4, correction_i32x4);
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
/** @brief Running state for i8 column sum precomputation on Power VSX. */
|
|
@@ -273,6 +273,12 @@ typedef struct nk_dot_f64x2_state_serial_t {
|
|
|
273
273
|
nk_f64_t compensations[2];
|
|
274
274
|
} nk_dot_f64x2_state_serial_t;
|
|
275
275
|
|
|
276
|
+
#if defined(__clang__)
|
|
277
|
+
#pragma clang attribute pop
|
|
278
|
+
#elif defined(__GNUC__)
|
|
279
|
+
#pragma GCC pop_options
|
|
280
|
+
#endif
|
|
281
|
+
|
|
276
282
|
NK_INTERNAL void nk_dot_f64x2_init_serial(nk_dot_f64x2_state_serial_t *state) {
|
|
277
283
|
state->sums[0] = 0, state->sums[1] = 0;
|
|
278
284
|
state->compensations[0] = 0, state->compensations[1] = 0;
|
|
@@ -808,6 +814,13 @@ NK_INTERNAL void nk_dot_i4x16_finalize_serial(nk_dot_i4x16_state_serial_t const
|
|
|
808
814
|
|
|
809
815
|
#pragma region Binary
|
|
810
816
|
|
|
817
|
+
#if defined(__clang__)
|
|
818
|
+
#pragma clang attribute push(__attribute__((noinline)), apply_to = function)
|
|
819
|
+
#elif defined(__GNUC__)
|
|
820
|
+
#pragma GCC push_options
|
|
821
|
+
#pragma GCC optimize("no-tree-vectorize", "no-tree-slp-vectorize", "no-ipa-cp-clone", "no-inline")
|
|
822
|
+
#endif
|
|
823
|
+
|
|
811
824
|
NK_PUBLIC void nk_dot_u1_serial(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n_bits, nk_u32_t *result) {
|
|
812
825
|
nk_u32_t dot = 0;
|
|
813
826
|
nk_size_t bytes = nk_size_divide_round_up_(n_bits, NK_BITS_PER_BYTE);
|
|
@@ -819,6 +832,12 @@ typedef struct nk_dot_u1x128_state_serial_t {
|
|
|
819
832
|
nk_u32_t dot_count;
|
|
820
833
|
} nk_dot_u1x128_state_serial_t;
|
|
821
834
|
|
|
835
|
+
#if defined(__clang__)
|
|
836
|
+
#pragma clang attribute pop
|
|
837
|
+
#elif defined(__GNUC__)
|
|
838
|
+
#pragma GCC pop_options
|
|
839
|
+
#endif
|
|
840
|
+
|
|
822
841
|
NK_INTERNAL void nk_dot_u1x128_init_serial(nk_dot_u1x128_state_serial_t *state) { state->dot_count = 0; }
|
|
823
842
|
|
|
824
843
|
NK_INTERNAL void nk_dot_u1x128_update_serial(nk_dot_u1x128_state_serial_t *state, nk_b128_vec_t a, nk_b128_vec_t b,
|
|
@@ -876,12 +895,6 @@ NK_INTERNAL nk_i32_t nk_sum_i4x32_finalize_serial(nk_sum_i4x32_state_serial_t co
|
|
|
876
895
|
|
|
877
896
|
#pragma endregion Stateful Element Sum Helpers
|
|
878
897
|
|
|
879
|
-
#if defined(__clang__)
|
|
880
|
-
#pragma clang attribute pop
|
|
881
|
-
#elif defined(__GNUC__)
|
|
882
|
-
#pragma GCC pop_options
|
|
883
|
-
#endif
|
|
884
|
-
|
|
885
898
|
#if defined(__cplusplus)
|
|
886
899
|
} // extern "C"
|
|
887
900
|
#endif
|
|
@@ -145,8 +145,8 @@ NK_INTERNAL void nk_dot_through_f32_init_skylake_(nk_dot_through_f32_state_skyla
|
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
147
|
* @brief Fuses 32-bit multiplication and accumulation for low-precision dot-products.
|
|
148
|
-
* @sa
|
|
149
|
-
* @sa
|
|
148
|
+
* @sa nk_dot_f16x16_update_skylake, nk_dot_bf16x16_update_skylake
|
|
149
|
+
* @sa nk_dot_e4m3x16_update_skylake, nk_dot_e5m2x16_update_skylake
|
|
150
150
|
*/
|
|
151
151
|
NK_INTERNAL void nk_dot_through_f32_update_skylake_(nk_dot_through_f32_state_skylake_t_ *state, nk_b512_vec_t a,
|
|
152
152
|
nk_b512_vec_t b, nk_size_t depth_offset,
|
|
@@ -188,8 +188,8 @@ NK_INTERNAL void nk_dot_e5m2x64_update_skylake_(nk_dot_through_f32_state_skylake
|
|
|
188
188
|
|
|
189
189
|
/**
|
|
190
190
|
* @brief Finalizes 4x low-precision dot-products placing them into 4x consecutive 32-bit slots.
|
|
191
|
-
* @sa
|
|
192
|
-
* @sa
|
|
191
|
+
* @sa nk_dot_f16x16_update_skylake, nk_dot_bf16x16_update_skylake
|
|
192
|
+
* @sa nk_dot_e4m3x16_update_skylake, nk_dot_e5m2x16_update_skylake
|
|
193
193
|
*
|
|
194
194
|
* The goal of this kernel is simple - compute 4x horizontal reductions, each involing 16x floats.
|
|
195
195
|
* The lack of vectorized horizontal instruction implies many consecutive shuffles producing a tree-like
|
|
@@ -691,21 +691,22 @@ NK_INTERNAL void nk_dot_u8x16_update_v128relaxed(nk_dot_u8x16_state_v128relaxed_
|
|
|
691
691
|
NK_INTERNAL void nk_dot_u8x16_finalize_v128relaxed( //
|
|
692
692
|
nk_dot_u8x16_state_v128relaxed_t const *state_a, nk_dot_u8x16_state_v128relaxed_t const *state_b, //
|
|
693
693
|
nk_dot_u8x16_state_v128relaxed_t const *state_c, nk_dot_u8x16_state_v128relaxed_t const *state_d, //
|
|
694
|
-
nk_size_t total_dimensions, nk_u32_t a_sum, nk_b128_vec_t
|
|
694
|
+
nk_size_t total_dimensions, nk_u32_t a_sum, nk_b128_vec_t const *b_sums_vec, nk_b128_vec_t *result_vec) {
|
|
695
|
+
nk_unused_(total_dimensions);
|
|
695
696
|
nk_unused_(a_sum);
|
|
696
697
|
// Σ a·b = reduce(lo) + 128·reduce(hi) + 128·Σb
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
698
|
+
result_vec->u32s[0] = (nk_u32_t)(nk_reduce_add_i32x4_v128relaxed_(state_a->product_low_i32x4) +
|
|
699
|
+
128 * nk_reduce_add_i32x4_v128relaxed_(state_a->product_high_i32x4) +
|
|
700
|
+
128 * (nk_i32_t)b_sums_vec->u32s[0]);
|
|
701
|
+
result_vec->u32s[1] = (nk_u32_t)(nk_reduce_add_i32x4_v128relaxed_(state_b->product_low_i32x4) +
|
|
702
|
+
128 * nk_reduce_add_i32x4_v128relaxed_(state_b->product_high_i32x4) +
|
|
703
|
+
128 * (nk_i32_t)b_sums_vec->u32s[1]);
|
|
704
|
+
result_vec->u32s[2] = (nk_u32_t)(nk_reduce_add_i32x4_v128relaxed_(state_c->product_low_i32x4) +
|
|
705
|
+
128 * nk_reduce_add_i32x4_v128relaxed_(state_c->product_high_i32x4) +
|
|
706
|
+
128 * (nk_i32_t)b_sums_vec->u32s[2]);
|
|
707
|
+
result_vec->u32s[3] = (nk_u32_t)(nk_reduce_add_i32x4_v128relaxed_(state_d->product_low_i32x4) +
|
|
708
|
+
128 * nk_reduce_add_i32x4_v128relaxed_(state_d->product_high_i32x4) +
|
|
709
|
+
128 * (nk_i32_t)b_sums_vec->u32s[3]);
|
|
709
710
|
}
|
|
710
711
|
|
|
711
712
|
typedef struct nk_sum_u8x16_state_v128relaxed_t {
|
|
@@ -1099,18 +1100,18 @@ NK_INTERNAL void nk_dot_i4x32_finalize_v128relaxed(
|
|
|
1099
1100
|
nk_dot_i4x32_state_v128relaxed_t const *state_c, nk_dot_i4x32_state_v128relaxed_t const *state_d, //
|
|
1100
1101
|
nk_size_t total_dimensions, //
|
|
1101
1102
|
nk_i32_t a_sum, /* Row sum of A (signed sum of i4 values) */ //
|
|
1102
|
-
nk_b128_vec_t
|
|
1103
|
-
nk_b128_vec_t *
|
|
1103
|
+
nk_b128_vec_t const *b_sums_vec, /* 4 × i32 column sums of B */ //
|
|
1104
|
+
nk_b128_vec_t *result_vec) {
|
|
1104
1105
|
// Match x86 compensated i4 finalizers: result = biased_dot - 8*(a_sum + b_sum) - 64*depth_padded
|
|
1105
1106
|
nk_i64_t depth_padded = (nk_i64_t)nk_size_round_up_to_multiple_(total_dimensions, 32);
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1107
|
+
result_vec->i32s[0] = nk_reduce_add_i32x4_v128relaxed_(state_a->biased_product_sum_i32x4) -
|
|
1108
|
+
8 * ((nk_i64_t)a_sum + (nk_i64_t)b_sums_vec->i32s[0]) - 64 * depth_padded;
|
|
1109
|
+
result_vec->i32s[1] = nk_reduce_add_i32x4_v128relaxed_(state_b->biased_product_sum_i32x4) -
|
|
1110
|
+
8 * ((nk_i64_t)a_sum + (nk_i64_t)b_sums_vec->i32s[1]) - 64 * depth_padded;
|
|
1111
|
+
result_vec->i32s[2] = nk_reduce_add_i32x4_v128relaxed_(state_c->biased_product_sum_i32x4) -
|
|
1112
|
+
8 * ((nk_i64_t)a_sum + (nk_i64_t)b_sums_vec->i32s[2]) - 64 * depth_padded;
|
|
1113
|
+
result_vec->i32s[3] = nk_reduce_add_i32x4_v128relaxed_(state_d->biased_product_sum_i32x4) -
|
|
1114
|
+
8 * ((nk_i64_t)a_sum + (nk_i64_t)b_sums_vec->i32s[3]) - 64 * depth_padded;
|
|
1114
1115
|
}
|
|
1115
1116
|
|
|
1116
1117
|
typedef struct nk_sum_i4x32_state_v128relaxed_t {
|