SIMD operations
Are there plans to implement SIMD operations?
No plans at the moment, but could potentially be added (although it'd be very slow of course). What's your use case? I'm not aware of anyone else using this library, so it'd be interesting to know what people want to use it for.
I'm trying to run Havok's Wasm on Babylon.js, but it seems to be using SIMD internally.
I'd also love SIMD support! I'm trying to polyfill WebAssembly so that I can run node on iOS, where using jitless mode has the side-effect of removing WebAssembly.
To be clear: Emulating WASM with SIMD would be much slower than emulating WASM without SIMD. This is worth pointing out because the only reason to run WASM with SIMD is to improve performance, but this would do the opposite. It would be much faster to build your WASM without SIMD support and then use that WASM on iOS instead.
You only want this library to support SIMD if you are unable to build WASM without SIMD support (i.e. all you have is a WASM binary containing SIMD instructions). Is that the case here?
Ah, interesting, thanks for the explanation. Then you're correct, I do not need SIMD support. Though a possible improvement could be to detect SIMD and throw an exception - I don't have the current behavior noted down, but it was not that.
For some more context, I'm using polywasm to load undici in an environment without WebAssembly. undici has this code:
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('../llhttp/llhttp-wasm.js') : undefined
let mod
try {
mod = await WebAssembly.compile(require('../llhttp/llhttp_simd-wasm.js'))
} catch (e) {
/* istanbul ignore next */
// We could check if the error was caused by the simd option not
// being enabled, but the occurring of this other error
// * https://github.com/emscripten-core/emscripten/issues/11495
// got me to remove that check to avoid breaking Node 12.
mod = await WebAssembly.compile(llhttpWasmData || require('../llhttp/llhttp-wasm.js'))
}
Currently, using polywasm directly breaks because it doesn't throw for undici to catch, and then fallback to non-SIMD. So I wrap polywasm and do this:
import {WebAssembly as WebAssemblyInterpreter} from 'polywasm'
import {decode} from '@webassemblyjs/wasm-parser/lib/index'
const containsSIMD = (wasmBuffer: BufferSource): boolean => {
let ast
try {
ast = decode(wasmBuffer)
} catch (e) {
if (e.message?.includes('Unexpected instruction')) {
return true
}
return false
}
for (const section of ast.body) {
if (section.type === 'CodeSection') {
for (const func of section.code) {
for (const instr of func.body) {
if (instr.opcode === 0xFD) {
return true
}
}
}
}
}
return false
}
const WebAssembly = {
...
async compile(bytes: BufferSource): Promise<WebAssemblyInterpreter.Module> {
if (containsSIMD(bytes)) {
throw new Error('[web-assembly@compile] SIMD is not supported.')
}
return WebAssemblyInterpreter.compile(bytes)
},
}
Anyways, my issue around SIMD is solved, but sharing in case you're interested in supporting this use-case within polywasm. Thanks for a great library!
Hey, I'm following up on this topic, as babylon.js/havok maintainers have explicitly stated they can't compile without SIMD and 6% of internet users still don't have access to webassembly simd, according to caniuse. Would it be technically possible to create a polyfill for SIMD features only, and have the rest run on wasm?