I worked on AAA engines that completely disregarded caches and branch prediction and while that worked great 10 years ago the same architecture became crippled on modern CPUs. Its so very easy to trash CPU resources that at this point I'm convinced most programs easily waste 90% of their CPU time.
For the last AAA title I shipped we spent weeks optimizing the threads scheduling, priorities and affinities along with profiling and whatnot; it was still an incredible challenge to use the main core above 80% and the other cores above 60%. If your architecture doesn't take the hardware into account from the ground up, you're not going to fully use the hardware :)
Hah, in my experience that's hopelessly optimistic. The C I write is probably 10-100x slower than it should be (leaving SSE and threading aside entirely), but the Python I write most days is a hundred times slower still.
* pure Python: 1.0x (baseline)
* NumPy (numeric python): 120x
* Google-optimized pure C: 2,500x
* optimized Python + Cython + BLAS: 8,700x
This is optimizing the same numeric algorithm (word2vec) using different languages and tricks, from naive pure-Python down to compiled Cython with optimized CPU-specific assembly/Fortran (BLAS) for the hotspots [0].
[0] http://rare-technologies.com/word2vec-in-python-part-two-opt...
Fortran yields some of the fastest code out of the box, yes, but C/C++ can yield equivalent performance by adhering to certain basic rules.
I did just that in C# last years and got at least two orders of magnitude of performance gain from it. Still, I constantly wished I was working in C instead :)
I don't know if that's strictly true, but I do feel games aren't as easy to split across threads/cores as many other types of software. Ultimately, a game boils down to one big giant blob of highly mutable and intertwined state (the world) that is modified very frequently with very low latency and where all reads should show a consistent view.
In other domains, avoiding interaction between different parts of your application state is a good thing that leads to easier maintenance and often better behavior. In a game, the whole point is having a rich world where entities in it interact with each other in interesting ways.
That's a common trope; it mostly applies to the rendering path. AI / Physic engines are nicely scalable with the number of cores (AI in particular, because a) it's oftern agent based, which naturally work concurrently and b) with AI, slighly relaxed synchronization constraints sometimes generate some desirable degrees of fuzziness and unpredictability ... although this is probably a very slippery slope ...)
Now it takes a change in perspective on how to structure code and data to properly exploit multiple cores to their full potential. It is certainly possible to have interaction in the game world and do it in a multi-core multi-threaded way, it just needs smarter structures and better organisation of data.
Game developers have and will adapt to this.
Games are still just an update and render pass in a loop. Nothing will change that, they might be decoupled and overlapped but they're still present. They're just much more complex than they used to be. Some engines will fork/join at every step (sometimes hundreds of times per frame), others will build task graphs and reduce them and a 3rd team will use fibers to build implicit graphs. No matter what you do you're still executing code with very clean sequential dependencies.
Game engines started going multi-core at least a decade ago. First by using one thread per system, then moving towards tasks. Today I don't know of any AAA game engine not already parallelizing its render path and unit updates massively.
You don't need interactions between entities at every point in time. There are very specific sync points during a frame and there isn't many of them (maybe 5 or 6). Your units can also be organized in a table where each row can be updated in parallel before moving on to the next.
Many types of software can get away using only concurrency or parallelism. Game engines have to master both. You want parallelism to crunch your unit updates and you want concurrency to overlap your render pass on top of the next frame's update pass.
See http://www.gamedev.net/topic/666419-what-are-your-opinions-o...
On consoles we get access to the hardware specs and profilers for everything - even if behind huge paywalls and confidentiality contracts. Yet with all that information available its still insanely hard to optimize the codebase.
There's absolutely no incentive to push these tools/specs to hobbyists because even professionals have a hard time getting them. Its also worth mentioning that having access to the tools and specs doesn't mean you'll understand how to properly use them.
In fairness, some of this design philosophy --- which Bernstein has held for a very long time! --- gets a lot clearer with the advent of modern ARX ciphers, which dispense with a lot of black magic in earlier block cipher designs.
A really good paper to read here is the original Salsa20 paper, which explains operation-by-operation why Bernstein chose each component of the cipher.
At some point the inequality gets too far out of whack and it's time to reconsider your values. Same reason we keep switching back and forth between dominant network architectures every 8 years. Local storage gets too fast or too slow relative to network overhead and everyone wants to move the data. Then we catch up and they move it back.