GPU.js
gpu.rocks
gpu.rocks
The headline feature is the translation of JavaScript into Shader code, but the underlying architecture that interfaces between arrays and textures is I think where the utility really comes in for me.
I think I'd actually be better off working with just that second part. Writing the kernels in a more native shader language but being able to pass in arrays and get arrays out the other end.
While the aspect of writing the shader itself in JavaScript is cool when you consider what it has to do to make it work, when it doesn't work it can be a real struggle to find out why.
Also there seems to be a bit of bit-rot in the documentation the link for the API reference is https://doxdox.org/gpujs/gpu.js/
Exactly like most GPGPU debugging then!
Having originally learned graphics programming before such tools existed I really can't get over how magic this feels.
- Minification: The JS code is transpiled at runtime and there's some subtle errors that can occur once you minify your code
- Performance: Each time you pass a JS array into GPU land, it's copying the data into a texture. If you want to do repeated calculations on the same data you should not be passing the arrays in each time because CPU/GPU data transfer will become a performance bottleneck.
- Math.atan2: the implementation is incorrect and I burned a few days because of it. I PR'ed the fix a few months ago but the library maintainer no longer seems active.
It's an awesome library. I write mostly GLSL now, but I still will write the initial algorithm and transpile is using GPU.js and then tweak the output accordingly.
And every time I see it, I cry that JavaScript doesn't have something like numpy.
numpy is just so damn logical and fast (and comprehensive!) that i don't consider myself a python programmer, i'm a numpy user.
EDIT: (removed complaint). That said: this looks like a good foundation for someone to use for implementing a fully featured numpy in JS.
It's compatible with both web and Node. In Node it uses https://github.com/stackgl/headless-gl to provide a WebGL compatible implementation as Node doesn't ship with GPU access out of the box. The project is looking into https://github.com/maierfelix/webgpu or similar to instead provide Node with a WebGPU compatible implementation. Both require N-API. The tracking issue can be found here for reference https://github.com/gpujs/gpu.js/issues/507.
Source: I'm the custodian/maintainer of headless-gl
> We need this [WebGPU] in GPU.js, possibly as a sub-project: https://github.com/maierfelix/webgpu Once it becomes stable, and well supported and tested, we could possibly make it the default fallback.
First they had a kind of OpenCL plugin, which died when plugins got widespread killed.
Then they finally managed to ramp enough quorum to add OpenGL compute shaders to WebGL 2.0, as an extension, just to have Google killing the efforts with "compute on the Web should be done via WebGPU".
So now it is time to wait again, until WebGPU actually makes it.
We are just getting to the situation where WebGL 2 carrying the GLES 3.0 feature set works in all browsers (Safari delayed it many years).
GLES 3.0 was released in 2012 (edit: fixed year) and WebGL 2 in 2017.
But apps take a long time to mature too of course, so good that developers can get a taste of WebGPU already.
Once I wrote a shader code of SHA256 Proof-of-Work:
Implementation for web-gl: https://github.com/gpujs/gpu.js/blob/1be50c09ed4edb7c7e846b1...
So users would need to know to go to their graphics settings page in order to get any benefit.
(The examples didn't seem to work on Chrome for Android atm though)
As long as you're willing to write the full scope of operations in a SIMD style, I'd bet that you could do it. But sparse is a lot more difficult to do than dense.
I know the basics of sparse matrix multiplication (there are many types: COO, CSR, LIL, etc. etc. Each representation would lead to a subtly different matrix multiplication algorithm). Load-balancing these operations across the GPU would be difficult, but it looks like major BLAS libraries have solved the problem already (ex: cuSPARSE, CUDA's sparse-matrix library for GPU compute)