AssemblyScript / assemblyscript

A TypeScript-like language for WebAssembly.
https://www.assemblyscript.org
Apache License 2.0
16.9k stars 660 forks source link

Multi-threading? #921

Open Iainmon opened 5 years ago

Iainmon commented 5 years ago

How would I go about creating threads in AssemblyScript? I am having trouble understanding the documentation.

dcodeIO commented 5 years ago

To enable threading one would compile with --enable threads --sharedMemory SIZE and share the memory instance between modules. However, the default runtimes do not currently support threading, so using threads isn't straight forward at this point and requires resorting to low-level code using the respective WebAssembly instructions directly.

A possible scenario at this point is to have a main thread that manages memory (--runtime half/full) and multiple workers (--runtime none) that perform computation on raw data provided and kept alive by the main thread, which should be safe as long as the workers do not interfere with memory management or GC and do not have own static data (no new, no stdlib, no strings etc.).

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

reconman commented 3 years ago

Seems like multithreading support was added in Chrome 74 by default, and I can't really find anything on how to use multithreading in AssemblyScript other than using Web Workers, which I want to avoid.

So, is there any update on this topic?

dumblob commented 3 years ago

Any update on this?

I was planning to use threading with AssemblyScript, but this issue makes me wonder whether I shouldn't rather stick with low-level WASM instead (which I wanted to avoid with the fear I would screw something up because I don't know the internals of AssemblyScript).

Ciantic commented 3 years ago

Please re-open. I was specifically looking for multi-threading support as well. Not sure how feasible it is to implement though but some clarification why it's not would be nice. Thanks!

MaxGraey commented 3 years ago

creating threads in WebAssembly happening on host side. AseemblyScript support atomics and shared memory but doesn't support thread safety for standard library yet. So if you avoid std allocs in shared memory it will be work. See example: https://blog.feather.systems/mandelbrot

dcodeIO commented 3 years ago

To give an update on the implementation details, the missing building block is still to make the runtime threading-aware, so a shared memory can be used. Right now, the runtime uses some globals, and globals are not shared across threads (only memory can be). With the globals moved to memory so these become shared and all threads see the same state, the next challenge would be to think about where and when to run the GC (probably on the main thread only), and locking / synchronization. In general the problem is that JS/TS hasn't been designed for this and one would use a WebWorker or similar there, so we'll either have to come up with something novel, or investigate how to wrap something safe into a WebWorker like API or similar.

MaxGraey commented 3 years ago

Well I like approach of Rayon. I did something similar for Swift in the past but without iterators. Also it was pretty similar to tbb::parallel_for. But it also need something more generic and abstract like Software Transactional Memory (SMT) or Actor model. In general, it is a matter of approach for whole language that requires research and working prototypes

trusktr commented 3 years ago

@MaxGraey any idea why the multi-threaded SIMD example is slower than the single threaded optimized examples? I'm on my Pixel 4 phone.

dumblob commented 3 years ago

I'm still interested in any contribution (even if it's just a subtle update on some background discussions) here.

munrocket commented 2 years ago

Also exist rayon-hash with different benchmarks of concurrent hash tables that can be placed in SAB's theoretically.

raddad772 commented 2 years ago

Bumping. Web workers support is lacking as well, since generated bindings use export. This means you can’t importScripts() and must use a web worker module. Currently this is not supported on Firefox and is very unreliable (silent failures) on Chrome. You’re basically forced to single thread right now, or use wasm, or edit auto generated bindings.

alienself commented 2 years ago

Same issue here, any progress on adding thread support to the runtime? Rust and C++ already support it in chrome with WASM.

raddad772 commented 2 years ago

C++ is not GC’d, and Rust is using LLVM so uses the same GC as their main implementation. My understanding of AssemblyScript’s GC is that it is…not as robust as that of Rust. Figuring out how to allocate and GC the memory shared between threads seems like a sore spot.

I’d really like the manual GC and no-GC runtimes to support threading even if the main runtime doesn’t anytime soon. It’s really not that hard to just free memory like you’re writing C. It could be made trivially easy with basic unique, shared and weak pointer analogs, which require some mechanism to guarantee execution at scope exit. Like Python’s finally clause, or C++ destructors. Would it be so hard to add finalizers that are called when an object goes out of scope?

dcodeIO commented 2 years ago

There is a finalization mechanism that can be hooked into by implementing a global __finalize function.

Regarding multi-threading, I wouldn't hold my breath at this point in time. At its core, JS is a single threaded language, and as such relies on workers and message passing to provide a form of threading. So that's about what to expect, yet our options are currently limited given that Wasm is still pretty barebones and a custom runtime must be bundled. I'd expect progress on this front no earlier than once we can drop the custom runtime and similar workarounds, replacing them with Wasm-native functionality, then hopefully bringing along a story to advance multithreading as well.

raddad772 commented 2 years ago

I hear what you're saying @dcodeIO , and appreciate all the work you guys do, but we have to have some direction better than this.

The point in using AssemblyScript is consistent performance. If you're not getting that, you may as well use JS or TS. And multi-threading is a big part of better performance. Especially for lower-spec phones, 90% of their main thread time is spent rendering a page, for instance. You'll do better spinning off a Web Worker than writing in AssemblyScript.

I'm facing this barrier now. I translated NES to AssemblyScript, which runs OK single-threaded, but now I am looking at SNES, which is going to require some fairly serious multi-threading.

At the very least we need an in-depth guide on how to do it the "manual" way using webassembly instructions. Then someone could write a "threads-as" library that encapsulates that and people could go on their ways for now.

Best option for now, I think, would be a way for WebAssembly's buffer to come from a SharedArrayBuffer, and be able to set boundaries for memory allocation. I.e. thread1 has 50MB of the heap, thread2 has 50MB more, thread3 has all the remaining space as the heap grows (and will be the "main thread"). That way you could manually instantiate different Web Workers, they could share memory, and you wouldn't have to make major changes to the current runtime. They would be a bit memory-constrained, but the proposal for multiple memories could fix this if you only allocate things locally and shared manually. Which is a fine way to do it. It'll get us SOMETHING.