diff --git a/web/packages/new/photos/services/ml/math.ts b/web/packages/new/photos/services/ml/math.ts index 28b3c1c5eb..7da08b3163 100644 --- a/web/packages/new/photos/services/ml/math.ts +++ b/web/packages/new/photos/services/ml/math.ts @@ -11,6 +11,19 @@ export const clamp = (value: number, min: number, max: number) => * the two given vectors. * * Precondition: The two vectors must be of the same length. + * + * [Note: Dot product performance] + * + * In theory, WASM SIMD instructions should give us a huge boost for computing + * dot products. In practice, we can get to roughly around the same performance + * by using Float32Arrays instead of number[], and letting the JS JIT do the + * optimizations for us. (This assertion was made on Chrome on macOS on Sep + * 2023, and may not hold in the future). + * + * We can get an extra 2x speedup over this by using some library that directly + * uses the SIMD intrinsics provided by the architecture instead of limiting + * itself to the WASM's set. But that requires bundling native code, so as a + * tradeoff to avoid complexity we live with leaving that 1x on the table. */ export const dotProduct = (v1: number[], v2: number[]) => { if (v1.length != v2.length) @@ -21,6 +34,16 @@ export const dotProduct = (v1: number[], v2: number[]) => { return d; }; +export const dotProductF32 = (v1: Float32Array, v2: Float32Array) => { + if (v1.length != v2.length) + throw new Error(`Length mismatch ${v1.length} ${v2.length}`); + let d = 0; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + for (let i = 0; i < v1.length; i++) d += v1[i]! * v2[i]!; + return d; +}; + + /** * Return the L2-norm ("magnitude") of the given vector. *