I think we should look at adding SIMD features to the ECMAScript specification.
I think this is justified for the following reasons:
- The current threading model isn’t very practical for when you have to do a lot of identical simple operations. I do not think we should eliminate multi-threading as currently implemented, but I do think SIMD features would allow this particular set of cases to be handled in a better way.
- WebAssembly has SIMD features now, albeit to a relatively limited degree. If the runtime systems work with this feature, they should at least theoretically be able to handle SIMD within more traditional web programming languages.
- Canvas elements are fundamentally graphical, as are SVG instances. SIMD is helpful for speeding up graphics processing and associated logic.
- Plenty of systems like Node and Bun require encryption for their client/server traffic for security reasons and this could make the performance hit from that less awful.
Here’s how I think SIMD could look in ECMAScript. Note that this is a first draft, and I admit that others will likely come up with better interface designs.
'use strict';
/*SIMD would either be provided as a module or just a value that's pre-created for you in your environment. I'm not sure yet.*/
const SIMD_multi_multi = SIMD.multiMulti;
const arrayA = [1, 2, 3, 5, 7, 11, 13];
const arrayB = [1, 2, 4, 8, 16, 32, 64];
const added = SIMD_multi_multi.add(arrayA, arrayB);
console.log(JSON.stringify(added)); //prints "[3,6,7,13,23,43,77]"
const SIMD_multi_single = SIMD.multiSingle;
const multiplied = SIMD_multi_single.multiply(arrayA, 2);
console.log(JSON.stringify(multiplied)); //prints "[2,4,6,10,14,22,26]"
const SIMD_single_multi = SIMD.singleMulti;
const subtracted = SIMD_single_multi.subtract(13, arrayA);
console.log(JSON.stringify(subtracted)); //prints "[12,11,10,8,6,2,0]"
My general idea for an interface is a single SIMD object. It would have the following members:
- SIMD.accelerationExists : This is a boolean. If true, hardware acceleration exists for SIMD and may or may not be used. If this is false, traditional Array methods are used as workarounds by the runtime engine. This value is constant and identical across all threads.
- SIMD.accelerationEnabled : This is a boolean. If true, hardware acceleration for SIMD operations will be used if executed. If false, it won’t be. This is because our code may or may not be the only code wanting to use hardware acceleration for SIMD. This value is not constant and may differ between threads.
- SIMD.multiMulti : This Object has a series of static methods which all take 2 Array-like objects and return an Array. All of these are analogous to the language's operators like the dot operation, add, subtract, boolean logic, bitwise boolean logic, etc. If the two arrays are of different lengths, then missing values are treated as 0, null, or empty strings. I’m not sure at time of writing which option is the least awful.
- SIMD.singleMulti: This Object has a series of static methods which all take a single value and an Array-like object and return an Array. All of these are analogous to the language's operators like the dot operation, add, subtract, boolean logic, bitwise boolean logic, etc.
- SIMD.multiSingle: This is effectively a reversed version of SIMD.singleMulti . SIMD.singleMulti.divide(25,[1,5,25]) would yield \[25,5,1\], and SIMD.multiSingle.mod([1,5,25],25) would yield \[1,5,0\]. Both of these are included because there are JS operations where order of operands matter. 7/3 is not 3/7, and the same is true if you’re working with arrays.
- SIMD.multi: This is for SIMD operations which are analogous to unary operators, such as negation, incrementing, and decrementing.
I get that this is a big feature to add, but I think it’ll be helpful. Please feel free to propose less awful interfaces.