729 karma · joined September 15, 2019
I don’t know why I never thought of this, brilliant!
Why not? I’ve heard people say this about C too and I never understood it: LLVM and GCC both have optimization passes that perform tail-call elimination.
The general rule of thumb is that within a generation, higher clock speed yields better performance per core. If you only have 32 data points, then you will probably get better performance with the 4 GHz 32-core CPU.
> if I'm doing a massive serial calculation does an individual core get to use the full cache
Your single core will get to use the entire L3 cache, but L2 and L1 caches are per-core and so your single core doing the work will not have access to those. So yes, there conceivably could be a benefit due to the larger L3 cache.
On a broader note, these kinds of factors (frequency, cache size, parallelism) tend to be extremely workload-specific and unpredictable, so the only real way to find out what's faster is to measure your specific workload.
Sort of? The stealing happens very rarely, only when the thread doesn’t have a page. It’s done using relaxed atomics, so synchronization is pretty mild in this case.
> bad data locality
This will be relevant when I make it NUMA-aware, but generally speaking this shouldn’t matter as each page is much bigger than a core’s L2 cache anyway. And also memory living in the deque is freed, I don’t think there’s generally expectations on locality of memory returned to you from the allocator.
^ actually it's basically implemented. I model-checked it with TLA+ and found a bug that I haven't fixed yet. Next up I'm writing a query engine on it.
Do any existing "thread-per-core" systems actually provide yield points as a thing you can do? Most of my experience is with OpenMP (using both BSP and task parallelism) and a little bit of TBB (also task parallelism). If you want to yield in these systems, you break it up into two tasks.
> if state is moved from one thread to another, this introduces synchronization costs
This isn't obvious to me. If you're moving state, then there is no synchronization because only one thread is touching the state at any given point. Unless we're talking about synchronization due to starting a new task?
Also I've heard that you can save an instruction when checking if your allocator is full by subtracting from the top, and checking the zero flag. It seems to complicate alignment logic. Does that ever end up mattering?
However, the data science/big data world has been bogged down by inefficient, clunky formats like Parquet for quite a while and so I applaud any steps towards bridging the gap between the two worlds.
It’s missing any kind of deeper statistics such as memory bandwidth, cache misses, branch mispredictions, etc. I think fundamentally Apple is geared towards application development, whereas I’m working on more HPC-like things.
Because I personally have tried, and found the code to be so code-golf and spaghetti-like that I gave up, it just wasn’t worth my time (even for the $1000 bounty).
I guess I am missing analytics, but I don't use those anyway out of respect for my readers' privacy.
Only one post at the moment (about Bloom filters), but I’m working on another one about compressing integers! My focus is on high performance data analytics—adjacent things.