| ▲ | Rendello 8 hours ago | ||||||||||||||||
I like SIMD, but before super-optimizing your code with SIMD and the like, really consider your data structures and access patterns. I've been singing Data-Oriented Design's praises, so I'll just collect all my comments here [1], but I think it's a good approach to optimization. I played around with SIMD in my old code (in Zig), but my approach to modelling datastructures was so antithetical to optimization, it was like putting high-performance racing tires on a lemon with a broken engine. It was the root-of-all-evil-type-premature-optimization, because I wasn't measuring performance, and I wasn't thinking about where the allocations were, etc. Now, I try to model my data as if it were SQL tables, see what my potential "primary keys" could be, and build my data structures around my access patterns. For example, I used to model trees as structs pointing to other structs on the heap:
Now my tree has all the bad characteristics of a linked list (* n nodes * m children), all the fragmentation of multiple heap vectors (* n nodes), and terrible set-up / tear-down time (in this case, Drop alone was taking up a good chunk of runtime).But a tree can be represented a million ways, and can always be linearized. So now I really consider my access/insert patterns of the tree, whether it's really a tree or some other sort of graph, whether I can store it in a Vec or a Struct of Vecs, etc. Since really looking at things through their access patterns and "primary keys", my code has been much faster and simpler. This has the added effect that a lot of your data ends up in homogeneous arrays / vecs, which means that the compiler can do its SIMD magic, the CPU can read it from your L1 cache a million times faster, etc. And then when you need to drop down into SIMD yourself, you can write some awesome branchless code. 1. https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que... | |||||||||||||||||
| ▲ | tarnith 8 hours ago | parent | next [-] | ||||||||||||||||
Yeah, data layout/cache aware layouts are really key if you really want to unlock making something that ends up in a hot loop fast with SIMD. Also, avoiding allocations or vtable lookups or a lot of indirection in the part of the code that's actually "hot" is really important. Vectors (in C++) at least aren't necessarily the best fit either, if you end up doing anything that can call an allocation unexpectedly. | |||||||||||||||||
| |||||||||||||||||
| ▲ | luaKmua 3 hours ago | parent | prev | next [-] | ||||||||||||||||
This is my eternal battle as a perf engineer. Performance starts with architecture and you can only squeeze so much out a hotpath with poor data layout. The nice part is that data-oriented code almost always easily supports threading and SIMD. | |||||||||||||||||
| |||||||||||||||||
| ▲ | Scene_Cast2 2 hours ago | parent | prev | next [-] | ||||||||||||||||
Very much agreed. Even more basic than that - memory access patterns are important. The amusing thing is that you end up writing GPU-style code even for CPU. For example - instead of an array of objects, using parquet-style object of arrays is one such trick. | |||||||||||||||||
| |||||||||||||||||
| ▲ | groundzeros2015 6 hours ago | parent | prev [-] | ||||||||||||||||
This. Tables are an efficient implementation of general graphs. It’s the best one I know of (unless your graph can be specialized). | |||||||||||||||||