Repository navigation
Reconsidering the binding strategy #838
Replies: 4 comments 13 replies
|
Hey, it's good to have you back. I am also in the process of moving, which should give me more free time for contributing and personal projects (some make us of wgpu) going forward. As I further try to incorporate wgpu and derived projects into my job and coursework. Whatever decision we end up making, we should put effort into not breaking existing projects. There is more and more use of I am very partial towards wgpu, because that is what I have learned to work with over the past years. Plus I have also been listening into the maintainers meeting(always wednesday at ~this time), where I will raise Regarding all the different binding options, I can't comment too much as I am not familiar with rust. But I much prefer getting more into rust than C++ honestly. Not just for pyodide, but we should improve the division for spec and native only features. Currently some native only features will just work if you include additional keys (think wireframe), are merged like limits, features and textures or need to be specifically imported from Generally, how much future maintainance work will there be? A couple of newer webgpu features are still outdated in wgpu (like texture tiers for example). But the I am excited about interoperability with pytorch, so finding a webgpu solution would be ideal (although after a few hours of looking around and working towards it, I am not so sure anymore), however a wgpu solution will also be fine. If we can extend supported platforms in the future (I am myself often with windows intel-xpu locally, but deploy training runs on different linux cuda clusters). Maybe we end up being the common interface for it. |
|
Seems like if we shown dawn + piodide you would be edit: satires -> satisfied |
My 2 cents is that this feels like the strongest proposal. In my limited amount of playing around with pyo3, I have found it really nice to work with.
This is not nothing but conda-forge maintains feedstocks for rust, maturin ect and if you lean into pixi you can make doing things like run ALL the tests (rust+python) something like Heres a mockup environment [workspace]
name = "wgpu-pyo3"
requires-pixi = ">=0.80"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]
[feature.build.dependencies]
rust = ">=1.97.1"
rust-src = ">=1.97.1"
maturin = ">=1.15,<2"
[tasks]
test = { cmd = "cargo test --locked && python -m pytest"} |
|
After considering many options and investigating consequences I propose we go with ArgumentsThis approach would be very performant. Since we'd bypass wgpu-native, we can benefit from its updates much faster, and can also use the internals, e.g. for shared memory. Also, we can turn on/off wgpu's compile-time features, since we build wgpu from source. Much more control! In terms of maintenance, this would turn this project in mostly Rust project, which definitely makes contributing for users harder. Some us us will have to be more accustomed to Rust. On the other hand, the Rust compiler will do a lot of validation, so I expect the codegen to be much simpler (only the IDL for the public API, really). And much of the code that we need is (in a slightly different form) already in wgpu-native. pyo3 supports compiling for the stable Python ABI, so we can publish wheels on Pypi that also work for future versions. With Emscripten 6.0.10, wgpu can also be compiled for Pyodide, which means we'd eventually only need a single backend. We'd have to wait for Pyodide to update to that version of Emscripten before we can actually make use of it though, see github.com/pyodide/pyodide/issues/6476 Some thoughts on DawnUsing Dawn has some temping features, like ready to use support for Emscripten, even though Mark's PR shows it requires some juggling to provide a Pyodide wheel for that. I also found the idea that Dawn can be with compiled to include Swiftshader quite appealing; it'd come with the same software backend on each platform. But we should be able to compile SwiftShader seperately and use it via wgpu also. Dawn being more ahead is of less concern as time progresses; wgpu is quite stable also (WebGPU is currently enabled by default in FF on Win/MacOS). On the other hand, wgpu has much more native features, which may be interesting for our partly scientific user base. A significant argument against using Dawn is that we'd introduce a split (we'd need a new name, since And finally, Rust, although not an easy language to learn, has a more modern compiler ecosystem than C++. wgpu vs wgpu-nativeBinding wgpu-native gave us a clear C-API, which is a kind of binding we're very used to. But it is also another indirection, and we did end up spending quite some time contributing to wgpu-native. With pyo3 we'd have a richer binding with a strict compiler and more control. Going forwardThe safest route is likely to add it as a new backend, and then deprecate and remove the wgpu-native backend. We can also push the raw JS backend further, since it seems close to finished. As @Vipitis said, we don't know yet wheter our raw JS backend is faster or slower than going through wgpu. I have some other priorities in the next couple of days, but plan to start on a more complete POC next week. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I think it'd be good to discuss and think about how we want this project to evolve further.
I've been away for quite a while (for personal reasons; prioritizing my family's well-being after moving to a new city). The fresh look on the project, plus @Korijn's proposed cffi refactor, gave rise to some questions ... luring me into a bit of a rabit hole, exploring several different options. Let me share my thoughts so far.
Primary goals
I we are going to change something fundamental about wgpu-py (or move our efforts to a new lib with similar goals), we'd want to have:
Some more thoughts and questions
I've been pretty strict on following WebGPU's spec as closely as possible, for two reasons: 1) it makes it easy for ppl to understand our API if they already know WebGPU, plus ample documentation available. 2) it should make it easier to implement the Pyodide/JS backend.
Question for @Vipitis: what is your current thought on this? I currently think that using a backend that compile to Pyodide would be preferable, because it safes us a lot of work and maintenance.
If we don't need our own JS backend, it gives us some breathing room to deviate some more from the WebGPU spec, where it makes sense. Or grow towards it more organically instead of enforcing it with codegen.
If we can support pyodide through the backend, I'd argue for just leaning into that backend and flatten the repo a bit.
Options worth exploring
Based on wgpu
Compared to Dawn, wgpu is certainly more of a community project. This feels nicer, but yeah ... it also feels that way because it lags behind and because wgpu-native is not getting the attention that it needs.
The Rust tooling is defintely friendlier than C++.
I think wgpu has more native-specific features.
Does anyone have any more arguments for either Dawn or wgpu?
wgpu-native wrapped with cffi (ABI mode)
Our current implementation.
wgpu-native wrapped with cffi (out-of-line)
@Korijn's work discussed in #827. Similar to our current implementation, but a dynamic lib is compiled as a build step.
wgpu wrapped with pyo3 and maturin
I took a small stab at this. It bypasses wgpu-native - and it's lack of development.
Using the Rust compiler feels nice.
wasm32-unknown-emscriptentarget, but wgpu only supportswasm32-unknown-unknown, emscripten seems not (yet) supported, also see wasm32-unknown-emscripten: unresolved __wbindgen_placeholder__ import prevents WebAssembly.instantiate() gfx-rs/wgpu#10274 (which is the exact error I got when I tried).If the Pyodide issue would be resolved, this might be my favorite option.
wgpu wrapped with nanobind
Nanobind is the successor to PyBind. It's for C++ but IIUC can also do C. I have not yet explored this option, but the result should be similar to cffi out-of-core. Except now the generated bindings are C++ instead of Python.
wgpu-native wrapped with mirror-bridge
https://chico.dev/Mirror-Bridge
Have not looked very closely yet. But wrapping C with it is probably not going to bring much benefit, and according to Claude, Dawn's C++ is not a good fit for mirror-bridge.
Based on Dawn
Dawn is ahead of wgpu, and battle-tested since it ships with all Chromium browsers. It has builtin support for sharing memory.
Dawn comes (from what I understand) with a performant CPU-based Vulkan backend. I see this as a big plus for running our image tests against, since the chance of it producing the exact same result is higher (maybe not when running in Docker with emulated aarch64). Plus it's a fallback that's actually feature complete!
Dawn wrapped with cffi ABI
Using the same approach as we currently do, but switching to Dawn. Not the best performance, but we keep maintainability and get a more mature WebGPU implementation, Pyodide support (probably), shared memory, and more.
Need to verify if we actually get all that. If this works, cffi out-of-core might also be feasible?
Dawn's C-API wrapped with cffi out-of-core
We might be able to change Korijn's work to go this route?
Big question: can we compile wasm wheels that work with pyodide?
Dawn wrapped with nanobind
Nanobind is the successor to PyBind. It's for C++ but IIUC can also do C.
I had Claude make a POC, but still need to take a look.
Big question: can we compile wasm wheels that work with pyodide?
Dawn wrapped with Cython
Quite similar in effect as the above, with friendlier code but more complex tooling, I assume.
Happy to hear more thoughts and experiences!
All reactions