-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: new annotation to convert array of structs (AoS) to struct of arrays (SoA) #64926
Comments
I think this is an interesting idea, but I don't think there's any significant precedent so far for a comment to materially influence the layout of a type in memory. I do see the benefit that it could therefore be backward compatible with older Go toolchain versions and other implementations, but historically that hasn't been a significant design constraint, and recent changes to the official toolchain have moved in the direction of making it easier to upgrade rather than easier to keep running older Go versions. That aside, this feels to me as one example of a more general idea of choosing between different machine representations of a single type at the Go level. I expect that a first decision to be made here is whether Go is the kind of language that aims to offer that sort of control over implementation details that aren't visible at the Go level of abstraction; if the answer to that is yes then I would prefer to see it specified in a way that suggests how other similar concerns could be met in the future. For example, Rust has the idea of a |
As another programming language example/prior art, Zig uses this layout extensively in its compiler to great effect. Zig has a syntax that makes looping through them very nice: https://zig.news/andrewrk/multi-object-for-loops-data-oriented-design-41ob. |
A SoA needs to be formally marked as a different kind of type. That means (or, arguably, regardless) this needs to be a language change proposal (with corresponding template). Ideally you could also precisely describe how this interacts with reflection – do we need a new reflect.Kind (probably yes)? do we need to add any other new reflection APIs (probably no)? |
Can you help justify this as a language change? I feel like this is the sort of thing which needs some experience. Like imagine:
This could generate some file
Then with the new ranging over functions stuff, you can imagine a method on |
Thanks for the proposal, but as @zephyrtronium points out this is simply impossible as written. I'm going to close this proposal. Please comment if you disagree. |
Proposal Details
Hi,
Here's a really common code example, of an array of structs (AoS):
However if the access pattern is to iterate over the same property, for each user, then for modern CPU caches, sometimes it can be more efficient to write code as a struct of arrays (SoA):
This can sometimes significantly improve performance. However, it's more cumbersome to write this way, and all call sites need to change. In a large codebase, it's hard to experiment with this idea.
I propose a new annotation that can automatically convert AoS declarations to SoA:
This would perform a compiler-internal transformation to use an SoA representation in memory.
Callers would still access fields as if AoS was used and the annotation were not present.
Any Go implementations not understanding the annotation would continue to treat the fields as AoS. This would affect older versions of the Go toolchain as well as TinyGo / gccgo.
One effect is each individual array element (e.g.
World[3]
) can no longer have its address taken to get a*User
.copy
builtin to support copying an AoS-ified struct to an ordinary one.The benefit of this proposal is to easily support transitioning to AoS in a large existing codebase.
Future work, the compiler could recognize some patterns (e.g. short accumulation loop) and use SIMD automatically.
This is based on previous work in other programming languages:
[10]Foo
to#soa[10]Foo
Foo[]
tosoa<Foo>
Foo :: struct { ...
toFoo :: struct SOA { ...
Supporting discussion:
The text was updated successfully, but these errors were encountered: