That's my point. Threading can also be easy in the highly intermingled execution parts. It's not full task threading but rather a calculated decision to use multiple threads on specific "slow" portions of the code. It's very seldom that you find any calculation code that works on single values. That's slow and inefficient. If there is that type of code in the application then those should be optimized first using something like Intel IPP. Once you are performing calculations on blocks of numbers then multiple threads can be used with minimal effort provided certain rules are followed.
For example, the flow of code might look like this (warning: dumb high level example to follow):
if (CollisionDetected)
{
DoStuffOnObject;
}
That flow wouldn't change at all. You can't change DoStuffOnObject to run in a different thread to CollisionDetected because it depends on it. What would would change is the code inside the DoStuffOnObject to do something like this:
Parallel.For(1, 12, ctr =>
{
work on block ctr
})
In other words, you are targeting specific blocks of code and only threading those. So you might take a specific block that is taking 24ms and by threading the code you can drop it down to 2ms. Assuming 6c/12t threads. For that split second, you will get a spike on all of the cores for the processing. You can pick these "critical paths", to steal a word from the project managers, and optimize those for multiple threads and quickly end up with much faster response time. You won't see all of the threads maxed out all of the time but the difference in 22ms will be very noticible in FPS.