TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Implementing a Struct of Arrays

123 pointsby mpweiher6 days ago

16 comments

PessimalDecimal6 days ago
I started thinking this would be a rehashing of how column-oriented storage formats can be far more efficient for certain access patterns. But it really was a showcase of what a bloated mess C++ has become.
评论 #43940598 未加载
评论 #43938351 未加载
评论 #43936886 未加载
评论 #43943872 未加载
Dwedit6 days ago
Struct of Arrays vs Array of Structs have different performance, depending on how they are accessed, mainly due to how memory will be cached.<p>If you are iterating over objects sequentially, and looking at every field, they will perform about the same. If you are iterating over objects sequentially, and only looking at a few fields, Struct of Arrays performs better. If you are accessing objects at random, and reading every field, Array of Structs performs better.<p>Array of Structs has a multiplication step when you calculate the address of an element. Struct of Arrays basically guarantees that the multiplication will be by a power of 2, so it&#x27;s a bitshift rather than a multiplication. (Unless your struct contains a type whose size is not a power of 2). Multiplication is still very fast though on most architectures, so that&#x27;s not all that much of a difference.
评论 #43939821 未加载
评论 #43941630 未加载
评论 #43939800 未加载
gr4vityWall6 days ago
Interesting article. It does show how modern C++ can be quite scary.<p>It reminded me of a Haxe macro used by the Dune: Spice Wars devs to transform an AoS into a SoA at compile time to increase performance: <a href="https:&#x2F;&#x2F;youtu.be&#x2F;pZcKyqLcjzc?t=941" rel="nofollow">https:&#x2F;&#x2F;youtu.be&#x2F;pZcKyqLcjzc?t=941</a><p>The end result is quite cool, though those compile time type generation macros always look too magical to me. Makes me wonder if just getting values using an index wouldn&#x27;t end up being more readable.
perihelions6 days ago
I attempted to write a minimal version of the idea in Common Lisp, if anyone was curious about how it&#x27;d look like in that language,<p><a href="https:&#x2F;&#x2F;peri.pages.dev&#x2F;struct-of-arrays-snippet" rel="nofollow">https:&#x2F;&#x2F;peri.pages.dev&#x2F;struct-of-arrays-snippet</a>
mac3n6 days ago
JOVIAL language had TABLE structures, which could be declared SERIAL or PARALLEL (<a href="https:&#x2F;&#x2F;ntrl.ntis.gov&#x2F;NTRL&#x2F;dashboard&#x2F;searchResults&#x2F;titleDetail&#x2F;PB82135062.xhtml" rel="nofollow">https:&#x2F;&#x2F;ntrl.ntis.gov&#x2F;NTRL&#x2F;dashboard&#x2F;searchResults&#x2F;titleDeta...</a> page 281).
the__alchemist6 days ago
I think I&#x27;ve lost the thread on the abstractions. (Me not being very familiar with Zig outside of its most basic syntax is probably why.) I&#x27;ve been doing a lot of SoA work in rust lately; specifically because I have numerical&#x2F;scientific code that uses CPU SIMD and CUDA; SoA works great for these.<p>The workflow is, I set up Vec3x8, and Quaternionx8, which wrap a simd instrinsic for each field (x: f32x8, y: f32x8...) etc.<p>For the GPU and general flattening, I just pack the args as Vecs, then the fn signature contains them like eps: &amp;[f32], sigma: &amp;[f32] etc. So, I&#x27;m having trouble mapping this SoA approach to the abstractions used in the article. Then the (C++-like CUDA) kernel sees these as *float3 params etc. It also feels like a complexity reverse of the Rust&#x2F;Zig stereotypes...<p>Examples:<p><pre><code> struct Vec3x8 { x: f32x8, y: f32x8, z: f32x8 } &#x2F;&#x2F; appropriate operator overloads... struct Setup { eps: Vec&lt;f32&gt;, sigma: Vec&lt;f32&gt;, } </code></pre> So, Structs of Arrays, plainly. Are the abstractions used here something like Jai is attempting, where the internal implementation is decoupled from the API, so you don&#x27;t compromise on performance vice ergonomics?
评论 #43943166 未加载
monkeyelite6 days ago
Interest in SOA is bringing to mind the “art of the meta object protocol” which argues for a stage between class definition and implementation that would allow you to choose the layout and access method for instances of a class.
评论 #43936783 未加载
评论 #43937198 未加载
评论 #43936682 未加载
sph6 days ago
<p><pre><code> define_aggregate(^^Pointers, nsdms(^^T) | std::views::transform([](std::meta::info member){ return data_member_spec(add_pointer(type_of(member)), {.name = identifier_of(member)}); })); </code></pre> What operator is ^^type?
评论 #43937142 未加载
评论 #43937108 未加载
TheHideout6 days ago
So, basically it&#x27;s allowing you to use a struct like you would in OOP, but get the array benefits of ECS when that struct is in a vector?
评论 #43936879 未加载
评论 #43938144 未加载
评论 #43936448 未加载
jayd166 days ago
Towards the middle you realize this is about the reflection more than anything else.<p>I do like how directly accessing the fields individually (the whole reason you would do this) is a hypothetical presented as an after thought. Enjoyably absurd.
gpderetta6 days ago
The use of reflection is interesting, but is there a significant advantage, compared to something like this:<p><pre><code> template&lt;template&lt;class&gt; class G&gt; struct Point { G&lt;int&gt; x; G&lt;int&gt; y; auto get() { return std::tie(x,y); } }; template&lt;template&lt;template&lt;class&gt; class&gt; class C&gt; struct SOA { template&lt;class T&gt; using Id = T; template&lt;class T&gt; using Ref = T&amp;; C&lt;std::vector&gt; vs; void push_back(C&lt;Id&gt; x) { std::apply([&amp;] (auto&amp;&amp;... r) { std::apply([&amp;](auto&amp;&amp;... v){ ( (r.push_back(v)),...); }, x.get()); }, vs.get()); } C&lt;Ref&gt; operator[](size_t i) { return std::apply([&amp;] (auto&amp;&amp;... r) { return C&lt;Ref&gt;{ r[i]...}; }, vs.get()); } }; int main() { SOA&lt;Point&gt; soa_point; soa_point.push_back({1,2}); auto [x,y] = soa_point[0]; }</code></pre>
评论 #43939479 未加载
gwenzek5 days ago
Interesting to see the new C++ at work. But also I&#x27;m sure it&#x27;s easier to learn Zig full language that just the new C++ metaprogramming
hinkley5 days ago
The problem I run into with these sorts of structures is the whole aggregation versus composition issue.<p>With composition the SoA problem is pretty simple. This object belongs to an owner or a category and it just never &#x27;moves&#x27; so the most naive solution is just fine.<p>I haven&#x27;t looked at C++ in a million years, but looks like this implementation fixes the aggregation problem by handing out handles to the data, but I don&#x27;t see anything in here where it tries to hand out the same handle for the same offset. I don&#x27;t know about C++ but that matters in some languages.
评论 #43944720 未加载
ozgrakkurt5 days ago
It is skeptical if this is even needed, why not design the structs etc. properly from the start so they are columnar if columnar works better?<p>Meta programming is never free
adzm5 days ago
Neat to see the reflection &#x2F; unibrow operator ^^ in the wild!
评论 #43947225 未加载
Enthouan6 days ago
I’m definitely missing the point, but reading the article, I kept thinking &quot;This would’ve been so much easier in C.&quot;
评论 #43938005 未加载
评论 #43937903 未加载
评论 #43937452 未加载